Part B. Etch a Sketch - darenl/etch-a-sketch GitHub Wiki

1. Describe which sensors you are using as inputs and why.

I am using potentiometers as the sensors for the x and y values so that I can get a range of fixed values. In addition, I use the button to reset the drawing context.

2. In what format does the server expect the X & Y values from the Arduino?

The server expects the X & Y values to be in a String, with the values separated by a comma, i.e. 'X-val,Y-val'.

3. What else does the Arduino need to do? The sensorCode folder has an almost working example.

The Arduino needs to read the values from the potentiometers and convert the values into the previously mentioned format. Then it must write the values to the Serial bus. It must also make sure the port for the Serial connection is 115200 so that the Raspberry Pi can receive them.

4. What range of output X & Y values do you need? Is it better to map the values from the inputs to the outputs in the Arduino code, the Node code or Client code ? Why?

The X & Y values must be within the dimensions of the screen otherwise they will not appear on the drawing context if the values exceed the width or height. Because it requires the dimensions of the screen, it is better to map the values in the client code. However, usually this should be done on the server code, which handles the data inputs so that the client does not need to do anything extra.

5. How often do you need to be sending data from the Arduino?

I send the data from the Arduino to the Raspberry Pi every 200 milliseconds.

6. Include a copy of the Arduino code, and a copy of your Server and client side code.

server.js

var express = require('express'); // web server application
var app = express(); // webapp
var http = require('http').Server(app); // connects http library to server
var io = require('socket.io')(http); // connect websocket library to server
var serverPort = 8000;
var serialPort = require('serialport'); // serial library
var readLine = serialPort.parsers.Readline; // read serial data as lines

//---------------------- WEBAPP SERVER SETUP ---------------------------------//
// use express to create the simple webapp
app.use(express.static('public')); // find pages in public directory


// start the server and say what port it is on
http.listen(serverPort, function() {
  console.log('listening on *:%s', serverPort);
});
//----------------------------------------------------------------------------//


//---------------------- SERIAL COMMUNICATION --------------------------------//
// start the serial port connection and read on newlines
const serial = new serialPort('/dev/ttyUSB0', {
 baudRate:115200

});
const parser = new readLine({
  delimiter: '\r\n'
});

// Read data that is available on the serial port and send it to the websocket
serial.pipe(parser);
parser.on('data', function(data) { // on data from the arduino
  if(data=='rst'){  // if its the 'rst' string call reset
    io.emit('reset');
  }else{ // any other data we try to forward by spliting it
    var transmitData = [data.split(',')[0],data.split(',')[1],data.split(',')[2]];
    io.emit('new-pos', transmitData);
  }
});
//----------------------------------------------------------------------------//


//---------------------- WEBSOCKET COMMUNICATION -----------------------------//
// this is the websocket event handler and say if someone connects
// as long as someone is connected, listen for messages
io.on('connect', function(socket) {
  console.log('a user connected');
  io.emit('reset'); // call reset to make sure the website is clean

// if you get the 'disconnect' message, say the user disconnected
  io.on('disconnect', function() {
    console.log('user disconnected');
  });
});

client.js

var COLOUR =  '#505050';  // This is the drawing color
var radius = 10;           // Constant radio for the line
var socket = io();        // websocket to the server
var previousPosition=[0,0]; // previous position to draw a line from
var ctx = Sketch.create(); //Creating the drawing context
var firstMessage=true;    // What the first message, to start on the first value

    ctx.container = document.getElementById( 'container' ); //reference drawing canvas
    ctx.autoclear= false; // making sure it stays
    ctx.retina='auto';
    ctx.setup = function() { console.log( 'setup' );} // Setup all variables
    ctx.keydown= function() { if ( ctx.keys.C ) ctx.clear();} // handeling keydowns

    socket.on('reset', function() { // on a 'reset' message clean and reste firstMessage
      firstMessage=true;
      ctx.clear();
    });

    socket.on('new-pos', function(data) { // handling new sensor values

      var newPosition = [data[0],data[1]];
      var ranValue = data[2];
      var r = 255 - ranValue;
      var g = 255 - Math.floor(ranValue/2);
      var b = 255 - Math.floor(ranValue/3);
      COLOUR = "#" + r.toString(16) + g.toString(16); + b.toString(16);
      
      if(firstMessage){ // if its the first message store that value as previous
        firstMessage=false;
        previousPosition=newPosition;
      }else{ // any other message we use to draw.
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';
        ctx.fillStyle = ctx.strokeStyle = COLOUR;
        ctx.lineWidth = radius;
        ctx.beginPath();  //begin a adrawing
        ctx.moveTo( previousPosition[0], previousPosition[1] ); // from
        ctx.lineTo( newPosition[0],  newPosition[1]); // to
        ctx.stroke(); // and only draw a stroke
        previousPosition=newPosition; // update to the new position.
       }
    });

Arduino Code

int xPin = A0;
int yPin = A1;
int xPos = 0;
int yPos = 0;

int rgbPin = A2;
int rgb = 0;

unsigned long targetTime=0;
const unsigned long interval=200; //TODO: How fast should we read
int buttonPin = 4;
int buttonState = 0;

void setup(){
	Serial.begin(115200);
	pinMode(buttonPin, INPUT);
}


void loop(){
	if(millis()>=targetTime){
		buttonState = digitalRead(buttonPin);
		if(buttonState == HIGH){
			Serial.println("rst");
		}
		else{
			xPos = analogRead(xPin);
			yPos = analogRead(yPin);
			rgb = analogRead(rgbPin);
			rgb = map(rgb, 0, 1023, 0, 255);
			String data = String(xPos) + "," + String(yPos) + "," + String(rgb) + "\r\n";
			Serial.println(data);
		}
		targetTime = millis() + interval;
	}
}