R: ARDUINO dengan RServe

From OnnoWiki
Revision as of 09:29, 25 November 2018 by Onnowpurbo (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Sumber: https://www.r-bloggers.com/connecting-the-real-world-to-r-with-an-arduino/


Connecting the real world to R with an Arduino October 2, 2012 By Markus Gesmann

inShare (This article was first published on mages' blog, and kindly contributed to R-bloggers)

Share Tweet

If connecting data to the real world is the next sexy job, then how do I do this? And how do I connect the real world to R?

It can be done as Matt Shottwell showed with his home made ECG and a patched version of R at useR! 2011. However, there are other options as well and here I will use an Arduino. The Arduino is an open-source electronics prototyping platform. It has been around for a number of years and is very popular with hardware hackers. So, I had to have a go at the Arduino as well. My Arduino starter kit from oomlout

The example I will present here is silly – it doesn’t do anything meaningful and yet I believe it shows the core building blocks for future projects: Read an analog signal into the computer via the Arduino, transform it with R through Rserve and display it graphically in real time. The video below demonstrates the final result. As I turn the potentiometer random points are displayed on the screen, with the standard deviation set by the analog output (A0) of the Arduino and fed into the rnorm function in R, while at the same time the LED brightness changes.

I don’t claim to be an expert in any of this (far from it), but at the end my experiment worked. I am happy to share my experience, as I have benefited from reading various blog posts as well. I can’t guarantee that any of this will not harm your hard- or software. Hence, I used an old computer. Of course feedback will be much appreciated if gently delivered.

Here is a list of hardware and software I used and 10 steps to recreate the experiment: Hardware

   Arduino (Uno)
   Computer (2003 iBook G4, MacOSX 10.4.11)
   USB cable
   Potentiometer (10k Ohm)
   Resistor (560 Ohm)
   LED
   Wire
   Bread-board

Software

   Arduino (1.0.1)
   Processing (1.5.1)
   Arduino library for Processing
   R (2.15.0)
   Rserve (0.6.8)
       REngine.jar
       RServeEngine.jar

Step 1

Install Arduino, Processing and R on your computer. I have used my old iBook G4, but the software is available for most platforms, including Windows and Linux.

Step 2

Assemble the hardware with the potentiometer, resistor and LED on a bread-board next to the Arduino. This setup is basically example 8 of my oomlout starter kit, with the difference that I connected the LED to Pin 9 instead of Pin 13. You find a detailed description, including video and code on their site. Image of my setup created with Fritzing

Step 3

Connect the Arduino with your computer via USB and start the Arduino software. You can reset the Arduino with a little sketch, if you want to:

void setup(){}
void loop(){}

Copy and paste the code below into a new Sketch and hit the upload button. The LED should light up and as you turn the potentiometer the brightness should change. While you upload the file to the Arduino notice the connection path of your device in the bottom of the console window, mine said: Arduino Uno on /dev/cu.usbmodem3B11.

Open the Serial Monitor in the Arduino software (Tools > Serial Monitor) and observe how the displayed numbers change from 0 to 1023 as you turn the potentiometer.


int led = 9;           // the pin that the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
   pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  analogWrite(led, brightness);    
  
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  
  // change the brightness for next time through the loop:
  brightness = map(sensorValue, 0, 1023, 0, 255);
 
  // print out the value you read:
  Serial.println(sensorValue);
  // delay in between reads for stability
  delay(50);         

}

view raw Set_time_for_Serial_Port.ino hosted with ❤ by GitHub

Step 4

Close the Arduino software and start Processing. You should get a similar window and IDE as with the Arduino software. Open the preference settings and find out where Processing stores the Sketches by default; mine are saved here: /Users/Markus/Documents/Processing. To make Processing talk to the Arduino it needs the Arduino library for Processing. Download the zip-file and extract it. Expanding the archive should result in a folder called arduino. If it doesn’t exist already, create the folder libraries in the default Processing Sketch folder, and place in there the arduino folder. Restart Processing, click on File > Examples … and a little window should list the new arduino library at the bottom. Step 5

Check the port number of the Arduino in Processing: The following little Processing sketch will list the serial ports in the console. Match the device paths listed against the one you noted in Step 3 and keep a record of the port number of the Arduino device path.

import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
void setup()
{
 println(Arduino.list()); 

}

view raw Check_serial_ports.pde hosted with ❤ by GitHub

Step 6

Test that you can read and write to the Arduino from Processing with the Sektch below. Change mySerialPort to the device number you identified in the previous step. Run the Processing code and you should see the potentiometer values displayed in the console window below your code. If you get any error messages regarding the RXTX library (most likely on a Mac) then check out the post by Ellen Sundh.

// LED connected to PIN 9
// Potentiometer on PIN 0
// Turn the potentiometer to change the brightness of the LED
import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int ledPin = 9;
int potPin = 0;
int mySerialPort = 7; // Change to your settings
void setup()
{
  println(Arduino.list());
  arduino = new Arduino(this, Arduino.list()[mySerialPort], 57600);
  arduino.pinMode(ledPin, Arduino.OUTPUT);
}

void draw()
{
  int val = arduino.analogRead(potPin);
  arduino.analogWrite(ledPin, val / 4); 

}

view raw Test_Arduino_via_Processing.pde hosted with ❤ by GitHub

Step 7

Open R and install the Rserve package, e.g. via the command install.packages("Rserve"). Start R, load the Rserve package and start the daemon, e.g.

library(Rserve)
Rserve()

or better via the command line:

R CMD Rserve

Step 9

Download the files REngine.jar and RServeEngine.jar from the Rserve page into a temporary folder. Those files are needed to connect Processing to R. More information around how to call R from Processing has the following post on the GuruBlog.

Step 10

Back to Processing. Create a new sketch in Processing, insert the code below and save the file. Add the two jar-files you downloaded in the previous step to your new sketch in Processing via Sketch > Add to File …

Fingers crossed. Hit the run bottom and a little window should come up, plotting random points from left to right and as you turn the potentiometer the vertical range of the plotted points should change as well.

/* This is skectch needs to run after my 
 Set_time_for_Serial_Port.ino
 Arduino sketch
 */

import processing.serial.*;
import org.rosuda.REngine.Rserve.*;
import org.rosuda.REngine.*;

int mySerialPort = 7; // Change this to the port number of the Arduino 
Serial myPort;        // The serial port
int xPos = 1;         // horizontal position of the graph
RConnection c;        // R connection variable
int ht = 512;         // Height of the graphic window
int wd = 512;         // Width of the graphic window

void setup () {
  // set the window size:
  size(ht, wd);
  smooth(); 

  // List all the available serial ports
  println(Serial.list());  
  // I know that the 7th port in the serial list on my Mac
  // is always my  Arduino, so I open Serial.list()[7].
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[mySerialPort], 9600);
  // don't generate a serialEvent() unless you get a newline character:
  myPort.bufferUntil('\n');
  // set inital background:
  background(55);
}
void draw () { 

  while (myPort.available () > 0) {
    // get the ASCII string:
    String inString = myPort.readStringUntil('\n'); 

    if (inString != null) {
      // trim off any whitespace:
      inString = trim(inString);
      // convert to float and map to the screen height:
      float serialValue = float(inString); 
      // map serialValue between 1 and half the window height value
      serialValue = map(serialValue, 0, 1023, 1, ht/2); 

      float[] den=null; // to store the R random figures  

      try {
        // Create a connection to R via Rserve
        RConnection c = new RConnection();  
        // get 100 random figures from a normal distribution
        // standard deviations set by potentiometer
        den = toFloatArray(c.eval("rnorm(100, 255, 0.5 * " + serialValue + ")").asDoubles());
        REXP x = c.eval("R.version.string");
        // println(x.asString());

        // plot random figures in a vertical lines as dots
        stroke(0, 128, 192);
        for (int i=0; i<100; i++) {
          line(xPos, den[i], xPos, den[i]);
        }
        den = null;
      } 
      catch ( REXPMismatchException rme ) {
        rme.printStackTrace();
      } 
      catch ( REngineException ree ) {
        ree.printStackTrace();
      }

      // Plot a circle with the potentiometer value mapped to 0 : 100 
      stroke(0, 128, 192);
      // colour the circle based on serialValue
      fill(map(serialValue, 1, ht/2, 0, width/2)); 
      ellipse(ht/2, wd/2, 80, 80);
      textAlign(CENTER);
      // colour the text based on serialValue, but in reverse order to the circle
      fill(map(serialValue, 1, ht/2, ht/2, 0)); 
      // place serialValue in the middle of the circle   
      text(map(serialValue, 1, ht/2, 0, 100), ht/2, ht/2+4);

      // at the edge of the screen, go back to the beginning:
      if (xPos >= width) {
        xPos = 0;
        background(55);
      } 
      else {
        // increment the horizontal position:
        xPos++;
      }
    }
  }
}

float[] toFloatArray(double[] arr) {
  // convert an array of doubles to floats
  // lots of functions in Processing seem to prefer floats
  if ( arr == null) return null;
  int n = arr.length;
  float[] ret = new float[n];
  for (int i = 0; i < n; i++) {
    ret[i] = (float) arr[i];
  }
  return ret;
}




Pranala Menarik