Arduino to Java data sent through USB - java

I am trying to get Accelerometer data into my Java application from Arduino at its IMU. When I run my Arduino program on Arduino IDE and bring up Serial Monitor data flow is really good. Unfortunatelly when I try to run my Java code something strange happens. I have to wait for 10 seconds and then about 1000 lines appear immediately. Then i have to wait for another 10-20 seconds and another 1000 lines of data appears.. Is Arduino sending data in packages ? Can't I get a single value right after its given to me from IMU ?
Arduino code :
#include <MPU9250.h>
#include <quaternionFilters.h>
#define AHRS true // Set to false for basic data read
#define SerialDebug true // Set to true to get Serial output for debugging
// Pin definitions
int intPin = 12; // These can be changed, 2 and 3 are the Arduinos ext int pins
int myLed = 13; // Set up pin 13 led for toggling
MPU9250 myIMU;
void setup()
{
Wire.begin();
Serial.begin(38400);
pinMode(intPin, INPUT);
digitalWrite(intPin, LOW);
pinMode(myLed, OUTPUT);
digitalWrite(myLed, HIGH);
byte c = myIMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250);
if (c == 0x71) // WHO_AM_I should always be 0x68
{
myIMU.MPU9250SelfTest(myIMU.SelfTest);
myIMU.calibrateMPU9250(myIMU.gyroBias, myIMU.accelBias);
myIMU.initMPU9250();
} // if (c == 0x71)
else
{
while(1) ;
}
}
void loop()
{
if (myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01)
{
myIMU.readAccelData(myIMU.accelCount); // Read the x/y/z adc values
myIMU.getAres();
myIMU.ax = (float)myIMU.accelCount[0]*myIMU.aRes; // - accelBias[0];
myIMU.ay = (float)myIMU.accelCount[1]*myIMU.aRes; // - accelBias[1];
myIMU.az = (float)myIMU.accelCount[2]*myIMU.aRes; // - accelBias[2];
}
myIMU.delt_t = millis() - myIMU.count;
if (myIMU.delt_t>20) // waiting some time to get less data
{
if(SerialDebug)
{
Serial.println(myIMU.ay*1000);
}
myIMU.count = millis();
myIMU.sumCount = 0;
myIMU.sum = 0;
}
}
Java code :
package perkusja;
import com.fazecast.jSerialComm.*;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JSlider;
public class Perkusja {
public static void main(String[] args) {
SerialPort[] ports = SerialPort.getCommPorts();
System.out.println("Select a port:");
int i = 1;
for(SerialPort port : ports)
System.out.println(i++ + ": " + port.getSystemPortName());
Scanner s = new Scanner(System.in);
int chosenPort = s.nextInt();
SerialPort serialPort = ports[chosenPort - 1];
if(serialPort.openPort())
System.out.println("Port opened successfully.");
else {
System.out.println("Unable to open the port.");
return;
}
serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 0, 0);
Scanner data = new Scanner(serialPort.getInputStream());
int counter =0;
while(data.hasNextLine()){
try{
// float kupa = data.nextFloat();
System.out.println(data.nextLine());
System.out.println("Line number : " + counter++);
}catch(Exception e){
System.out.println("ERROR");}
}
}
}
I've been following this tutorial : https://www.youtube.com/watch?v=8B6j_yr9H8g&t=392s
Im using Arduino ProMicro from sparkfun and IMU - MPU9250 also from sparkfun

Related

Java's System.out.println(); will it block the program it tty will have latency

I will run the program over very slow ssh connection. Will it slow down or block the
System.out.println();
on big loads of printing. So if it prints few gigabytes right into console, but my connection is slow - where undiplayed data will appear? what is the size of tty memory? If I will lose connection for a while - will it run still?
No. PrintWriter does not wait for confirmation of completion.
Will it block the program it tty will have latency
Java's console output is blocking, so potentially your code may block, especially when you writing a lot of data.
what is the size of tty memory?
I am pretty sure that it depends on your kernel, this old thread suggests that it was 4096 bytes at some moment:
I've looked in the kernel code (linux\drivers\char\serial.c) and there is a #define called SERIAL_XMIT_SIZE. At first I thought maybe I could change that but it seems that the transmit buffer is actually fixed to be a memory page (4k).
If I will lose connection for a while - will it run still?
Yes, and if there is no one connected to the tty, then it will run much faster, as it will be able to discard the data.
Also small test application that simulates your use-case.
Echo.java
import java.io.IOException;
public class Echo {
public static void main(String[] args) throws InterruptedException, IOException {
final byte[] data = new byte[Test.BODY_LENGTH + Test.END_MARKER.length];
int index = 0;
outer: while (true) {
data[index++] = (byte) System.in.read();
final int dataOffset = index - Test.END_MARKER.length;
if (dataOffset < 0) {
continue;
}
for (int i = 0; i < Test.END_MARKER.length; i++) {
if (data[dataOffset + i] != Test.END_MARKER[i]) {
continue outer;
}
}
System.out.print(new String(data, 0, index));
return;
}
}
}
Test.java
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public class Test {
public static final byte[] END_MARKER = "$TERMINATE$".getBytes();
public static final int BODY_LENGTH = 1024768;
public static void main(String[] args) throws IOException, InterruptedException {
StringBuilder data = new StringBuilder();
for (int i = 0; i < BODY_LENGTH; i++) {
data.append((char) ('a' + ThreadLocalRandom.current().nextInt(('z' - 'a' + 1))));
}
final Process process = new ProcessBuilder("java", Test.class.getPackage().getName() + ".Echo")
.directory(new File("out/production/week 3")) // Change to your output directory
.start();
process.getOutputStream().write(data.toString().getBytes());
process.getOutputStream().write(END_MARKER);
process.getOutputStream().flush();
System.out.println("Written!");
final boolean exitedAfterWroteData = process.waitFor(5, TimeUnit.SECONDS);
System.out.println(exitedAfterWroteData ? "Complete" : "Running"); // Will print running after 5 seconds
int read = 0;
while (process.getInputStream().read() > -1) {
read++;
}
if (read != data.toString().getBytes().length + END_MARKER.length) {
throw new IllegalStateException("Expected echo to print exactly " + BODY_LENGTH + END_MARKER.length + " symbols!");
}
final boolean exitedAfterWeReadData = process.waitFor(50, TimeUnit.MILLISECONDS);
System.out.println(exitedAfterWeReadData ? "Complete" : "Running"); // Will print complete after a few milliseconds
}
}

Received Byte array not always correct

I have an Arduino program that sends via Bluetooth a byte array to a Java program.
The Java program receives the data on JSSC. The array is 72 bytes long (18 floats a´ 4byte).
How JSSC recognizes the end of transmission, or know that a new byte array becomes available?
In most cases, the transfer is correct. But from time to time waste is received.
I've found this example here.
http://www.javaprogrammingforums.com/java-se-api-tutorials/5603-jssc-library-easy-work-serial-ports.html
This
if(event.getEventValue() == 10)
means an linefeed, but bytearray have no linefeeds.
Arduino:
Serial.write(bytearray, size of bytearray);
Java:
class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
int dataNumber = 0;
try {
if(event.isRXCHAR()){
if(event.getEventValue() >= BYTE_NUMBER){
receivedByte = usbPort.readBytes(BYTE_NUMBER);
if(receivedByte != null) {
isRequestOK = true;
byte[] myArray = new byte[FLOATSIZE];
for(int i = 0, y = 0; i < receivedByte.length; i++, y++) { //i < receivedByte.length-1
if(myArray == null) {
y = 0;
myArray = new byte[FLOATSIZE];
}
if((i + 1) % FLOATSIZE != 0) {
myArray[y] = receivedByte[i];
}
else {
myArray[y] = receivedByte[i];
receivedValue[dataNumber] = ByteBuffer.wrap(myArray).order(ByteOrder.LITTLE_ENDIAN).getFloat();
myArray = null;
dataNumber++;
}
}
}
}
}
} catch (SerialPortException e) { } ///InvocationTargetException oder NullPointerException
}//--------------------------- End of serialEvent -------------------------------------------------------------
}//--------------------------- End of SerialPortReader ------------------------------------------------------------
Can anybody help me?
Best regards Willi
P.S. This is my first question in this forum. Hopefully I have followed the rules.

Fast Fourier Transform in processing of an input signal from Arduino

I have been trying to get audio signal from an arduino microphone. First I setup my arduino in Free Running Mode, and then I wait for a message from Processing that is a capital A. When Processing sends the serial signal, my arduino should send back 16 audio amplitude samples. Then, processing should take those 16 audio samples and pass them by the Fast Fourier Transform in orden to get a real time frequency spectrum. However, it seems that my Arduino never detects the capital A, and also, if I try to send the samples from my Arduino without waiting for the capital A, when Processing gets the samples it seems something went wrong with the serial communication. I tried with many arduinos and different serial cables to be sure it was no the problem. Here you are the arduino code:
// Arrays to save our results in
int values[16];
// Define various ADC prescaler
const unsigned char PS_16 = (1 << ADPS2);
const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
const unsigned char PS_64 = (1 << ADPS2) | (1 << ADPS1);
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
// Setup the serial port and pin 2
void setup() {
Serial.begin(115200);
pinMode(2, INPUT);
// set up the ADC
ADCSRA &= ~PS_128; // remove bits set by Arduino library
// you can choose a prescaler from above.
// PS_16, PS_32, PS_64 or PS_128
ADCSRA |= PS_64; // set our own prescaler to 64
}
void loop() {
unsigned int i;
for(i=0;i<16;i++) {
values[i] = analogRead(2);
}
if(Serial.available() > 0) {
char c = Serial.read();
if(c == 'A') {
for(i=0;i<16;i++) {
Serial.println(values[i]);
}
}
}
delay(10);
}
Here you are the processing code:
import processing.serial.*;
import ddf.minim.analysis.*;
FFT fft;
Serial myPort; // Create object from Serial class
void setup()
{
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 115200);
size(800, 600);
background(255);
fft = new FFT(16, 16000);
}
String mensaje;
float[] magnitudes = new float[16];
int contador = 0;
byte request = true;
void draw()
{
if(request) {
myPort.write('A');//Solicita nuevos datos.
request = false;
}
while(!request) {
if(myPort.available()>0) {
mensaje = myPort.readStringUntil(13);
print(" mensaje: "+mensaje);
if(mensaje != null){
magnitudes[contador++] = int(mensaje);
}
}
if(contador >= 15) {
contador=0;
fft.forward(magnitudes);
request = true;
fill(100);
rect(0,0,800,800);
for (int i = 0; i < 15; i++) {
fill(200);
rect(i*30+10, 0, 10, fft.getBand(i) * 0.1);
}
}
}
}
Thank you a lot for your attention!

Processing Serial Read from Arduino causing Java PApplet error

I am reading serial data from an arduino sketch that I uploaded to a teensy 2.0 / this also occurs when running a regular arduino. I am then splitting the strings and converting into an integer array with Processing’s int() function, in order to be able to trigger sounds. The arduino sketch is reading in capacitive sensor data. It runs well for about 10-15s and then starts throwing up the following error.
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.core.PApplet.parseInt(PApplet.java:9127)
at processing.core.PApplet.parseInt(PApplet.java:9113)
at NightGames_Tree.draw(NightGames_Tree.java:59)
at processing.core.PApplet.handleDraw(PApplet.java:2266)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
at processing.core.PApplet.run(PApplet.java:2140)
at java.lang.Thread.run(Thread.java:695)
My code is as follows:
In Arduino:
#include <CapacitiveSensor.h>
CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2);
void setup()
{
cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}
void loop()
{
long start = millis();
long total1 = cs_4_2.capacitiveSensor(30);
Serial.print(millis() - start); // check on performance in milliseconds
Serial.print("\t");
Serial.print(total1); // print sensor output 1
Serial.println("\t");
delay(100);
}
In Processing:
import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;
import processing.serial.*;
Minim minim;
AudioPlayer tree1;
AudioPlayer tree2;
Serial myPort;
String val;
void setup(){
String portName = Serial.list()[12]; // calls on the port which teensy is on
myPort = new Serial(this, portName, 9600);
println(Serial.list()); // prints list of ports that processing can access
//setup sound
minim = new Minim(this);
tree1 = minim.loadFile("tree1.aif");
}
void draw()
{
if (myPort.available() > 0) {
val = myPort.readStringUntil('\n');
int[] list = int(split(val, '\t')); // splits string into list based on tab after
int sum = 0;
int sum1 = 0;
// print(list.length);
sum = sum + list[0];
sum1 = sum1 + list[1];
print(sum);
print('\t');
print(sum1);
print('\t');
print('\n');
//print(val);
if (sum1 > 500) {
tree1.play(0);
} else if (sum1 <500){
}
}
}
When the error shows up after running for a while, Processing highlights this line of code
int[] list = int(split(val, '\t'));
Thanks in advance for any help. I am running this on a Mac.
I ran this on a Windows box, using Processing 3.0a4 and Arduino 1.6.3
On Arduino, I commented out everything having to do with the capacitive sensor library because I didn't have it. `
//#include <CapacitiveSensor.h>
//CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2);
void setup()
{
// cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
// turn off autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}
void loop()
{
long start = millis();
// long total1 = cs_4_2.capacitiveSensor(30);
Serial.print(millis() - start);
// check on performance in milliseconds
Serial.print("\t");
//Serial.print(total1); // print sensor output 1
Serial.println("\t");
delay(100);
}
In Processing I commented out the line with the sound file.
The error I got pointed to this line:
int[] list = int(split(val, '\t'));
It seems possible that there is a type mismatch that allows the list to stream for a short bit but them jams up the processor.
Turns out processing was detecting a null object so adding a check for null objects solved the problem. The condensed code is:
import processing.serial.*;
Serial myPort;
String val;
void setup(){
String portName = Serial.list()[12]; // calls on the port which teensy is on
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if (myPort.available() > 0) {
val = myPort.readStringUntil('\n');
if (val!=null){
int[] list = int(split(val, '\t')); // splits string into list based on tab
int sum = 0;
int sum1 = 0;
int sum2 = 0;
sum = sum + list[0];
sum1 = sum1 + list[1];
sum2 = sum2 + list[2];
print(sum);
print('\t');
print(sum1);
print('\t');
print(sum2);
print('\t');
print('\n');
}
}
}

USB Serial for Android - problems sending/receiving data with Arduino Uno R3

I'm trying to send a command such as "c" or "s" to the Arduino from my Android applicaton. The device is recognized, but I'm unsure if I'm sending/receiving the data correctly. I'm using the USBSerialforAndroid library.
When I tap my buttons to start and stop the measurements, the toast notifications pop up to signify that they are going through, but when data is "received" I'm getting back either "7.00" or "0.00", which I know are wrong. I feel like it may be within my Arduino code, or how I'm sending bytes from the app.
Here is the relevant Android code:
startMeasurement.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (selectedSensorType.equals("grade")) {
//do nothing
} else if (selectedSensorType.equals("height")) {
startCode = "c";
heightStart = serialUser(startCode); //get heightFloor from Arduino
} else if (selectedSensorType.equals("distance")) {
startCode ="s";
distanceStart = 0;
}
}
});
saveMeasurement.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (selectedSensorType.equals("grade")) {
check.setText(String.format("%.2f", outputGrade));
} else if (selectedSensorType.equals("height")) {
endCode = "c";
heightEnd = serialUser(endCode); //get heightCurb from Arduino
double measuredHeight = heightEnd - heightStart;
check.setText(String.format("%.2f", measuredHeight));
} else if (selectedSensorType.equals("distance")) {
endCode = "e";
distanceEnd = serialUser(endCode); //get distanceEnc from Arduino
double measuredDistance = distanceEnd - distanceStart;
check.setText(String.format("%.2f", measuredDistance));
}
}
});
Here is my serialUser() method:
private double serialUser(String command) {
double output = 0;
if (mSerialDevice != null) {
byte[] commandArray = command.getBytes();
byte[] returnArray = new byte[8];
try {
mSerialDevice.setBaudRate(115200);
mSerialDevice.write(commandArray, 1000);
output = mSerialDevice.read(returnArray, 2500);
} catch (IOException e) {
e.printStackTrace();
}
}
return output;
}
And here is my Arduino code:
void setup()
{
Serial.begin(115200);
Dist.begin(2,3);
}
const double Pi = 3.14159265359; // 3.141593, set to 1 for testing purposes
double encoderPosition = -999;
void loop()
{
double newPosition = abs(myEnc.read()); // gets raw data, 1440 ticks = 1 rev
double revs = newPosition/(double)960; // calculates number of revs
double diameter = 15; // specify wheel diameter
double distanceEnc = diameter*Pi*revs; // calculates distance
double heightDiff;
int timesum = 0;
distanceEnc = round(distanceEnc*1000.0l)/1000.0l; // round distance to 3 decimal places
if (newPosition != encoderPosition) { // write new position to serial
encoderPosition = newPosition;
//Serial.println(distanceEnc,3);
//Serial.println(revs,3);
}
while (Serial.available()) { // if a character is sent to the device, the encoder reading resets to zero
byte incomingCommand = Serial.read();
if (incomingCommand == 's'){
myEnc.write(0);
revs = 0;
}
if (incomingCommand == 'e'){
Serial.println(distanceEnc,3);
}
if (incomingCommand == 'f'){
time = Dist.getDistanceTime();
heightFloor = (float) time/(148.00);
Serial.println(heightFloor);
}
if(incomingCommand =='c'){
for(int i=1; i<11; i++){
times[i] = Dist.getDistanceTime();
delay(100);
timesum = timesum+times[i];}
time = timesum/(int)10;
heightCurb = (float) time/(148.00);
heightDiff = heightFloor - heightCurb;
Serial.println(heightCurb);
}
}
}
I used the example from the developer's example folder to build a working app.
https://github.com/mik3y/usb-serial-for-android/tree/master/usbSerialExamples
Check these out, and see what you can make of it.

Categories