Fast Fourier Transform in processing of an input signal from Arduino - java

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!

Related

How to write a file in a smart card with java card

Hello i'm a beginner on the use of javacard ! I want to write a file (less than 1024kb) in my smart card so what i do is to transform the file to an array of byte (byte[]), for example i have an array with the length of 638 ! My code to write and read the data works fine (no error) but when i read the data from the smart card and compare it to the default array, they are not same (same length but different content). I read a lot of topic here but i was unable to find one which can solve my problem ! Thank you for help
I use JCDK 2.2.2
My applet that read and write data:
.....
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
switch(buffer[ISO7816.OFFSET_INS]) {
case INS_SET_DATA:
// byte bufferDataLength = (byte)(apdu.setIncomingAndReceive());
//We want to start data copy
if (buffer[ISO7816.OFFSET_P1] == 0x00 && buffer[ISO7816.OFFSET_P2] == 0x00) {
data = new byte[(short) 638];
} else {
// copying the apdu data into byte array Data
// array copy: (src, offset, target, offset,copy size)
Util.arrayCopyNonAtomic(buffer, (short) ISO7816.OFFSET_CDATA, data,
(short) ((short) buffer[ISO7816.OFFSET_P1] * 100),
(short) buffer[ISO7816.OFFSET_P2]
);
}
break;
case INS_GET_DATA:
// array copy: (src, offset, target, offset,copy size)
short t = (short)(buffer[ISO7816.OFFSET_P2] & 0xFF);
short o = (short)(buffer[ISO7816.OFFSET_P1] & 0xFF);
Util.arrayCopyNonAtomic(data, o, buffer, ISO7816.OFFSET_CDATA, t);
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, t);
break;
}
}
.....
The code i use to send the data to the smartcard (apduio package of JCDK 2.2.2)
.....
switch(choice) {
case 8:
byte[] configData = fileToByteArray("D:\\jcard\\config.dat");
byte[] chunk = new byte[100];
System.out.println("Config Length: " + configData.length); // Got 638
int configLength = configData.length;
double round = Math.floor((double)configLength / 100);
int lastPart = configLength % 100;
System.out.println("Round : " + round); // Got 6
System.out.println("Last Part : " + lastPart); // Got 38
double partToSend = lastPart == 0 ? round : round + 1;
//Initialize the array of byte in my applet to have the length of data i want to write in
apdu.command[Apdu.INS] = MyAppletClient.INS_SET_DATA;
apdu.command[Apdu.P1] = 0x00;
apdu.command[Apdu.P2] = 0x00;
cad.exchangeApdu(apdu);
handleResponse(apdu);
boolean allPartSend = true;
for (int i = 0; i < round; i++) {
//array copy: (src, offset, target, offset, copy size)
System.arraycopy(configData, (i * 100), chunk, 0, 100);
System.out.println("Data Length: " + chunk.length); // Got 100
apdu.command[Apdu.P1] = (byte) i;
apdu.command[Apdu.P2] = 100;
apdu.setDataIn(Data);
cad.exchangeApdu(apdu);
if (apdu.getStatus() != 0x9000) {
System.out.println("["+i+"] An error occurred with status: " + apdu.getStatus());
allPartSend = false;
break;
}
}
if(allPartSend) {
byte[] finalPart = new byte[lastPart];
System.arraycopy(configData, (int) (round * 100), finalPart, 0, lastPart);
apdu.command[Apdu.P1] = (byte) round;
apdu.command[Apdu.P2] = (byte) lastPart;
apdu.setDataIn(finalPart);
cad.exchangeApdu(apdu);
if (apdu.getStatus() != 0x9000) {
System.out.println("An error occurred with status: " + apdu.getStatus());
break;
} else {
System.out.println("OK");
}
} else {
System.out.println("Fail to send all data");
}
break;
case 9:
int cfgLength = 638; //Because i know the array has that length
byte[] res = new byte[cfgLength];
double rnd = Math.floor((double)cfgLength / 100);
int last = fpLength % 100, readLength = 0;
boolean allSend = true;
for(int i = 0; i < rnd; i++) {
apdu.command[Apdu.INS] = MyAppletClient.INS_GET_DATA;
apdu.command[Apdu.P1] = (byte) (i * 100);
apdu.command[Apdu.P2] = 100;
cad.exchangeApdu(apdu);
if (apdu.getStatus() != 0x9000) {
System.out.println("An error occurred with status: " + apdu.getStatus());
} else {
readLength += apdu.dataOut.length;
// System.out.println("Datalength : " + apdu.dataOut.length); // Got 100
//array copy: (src, offset, target, offset, copy size)
System.arraycopy(apdu.dataOut, 0, res, (i*100), apdu.dataOut.length);
}
}
if(allSend) {
apdu.command[Apdu.INS] = MyAppletClient.INS_GET_DATA;
apdu.command[Apdu.P1] = (byte) ((int)rnd * 100);
apdu.command[Apdu.P2] = (byte) last;
cad.exchangeApdu(apdu);
if (apdu.getStatus() != 0x9000) {
System.out.println("An error occurred with status: " + apdu.getStatus());
break;
} else {
readLength += apdu.dataOut.length;
//array copy: (src, offset, target, offset, copy size)
System.arraycopy(apdu.dataOut, 0, res, (int)(rnd * 100 ), apdu.dataOut.length);
}
} else {
System.out.println("Fail to get all the part");
}
byte[] cfgData = fileToByteArray("D:\\jcard\\config.dat");
System.out.println("ReadLength : " + readLength); // Got 638
System.out.println("Array equals : " + Arrays.equals(cfgData, res)); // Got false but expected true
break;
}
}
.....
It looks like you are mixing ISO case 1 and 3 commands. An ISO case 1 means that no CDATA or RDATA is present, and ISO case 3 means just CDATA, no RDATA. Generally it is best to let a command be only one of the possible 4 cases (case 2 is just RDATA and case 4 both CDATA and RDATA. For instance, you can create a CREATE RECORD command or something similar.
You should call setIncomingAndReceive right before copying the data to the array. If you do not do this then only part of the data may be present in the buffer. Note though that setIncomingAndReceive is a convenience method, and you may be able to find better methods for handling large amounts of data.
Note that ISO 7816-4 already defines a file based card system; copying part of that existing standard may be more useful than creating your own from scratch. Also note that you should prefer APDU#getOffsetCdata rather than the constant. That method is compatible with extended length APDU's, and you may want to upscale to those in the future.
My guess is that the reason why you are receiving different data from the one you wrote to the card is this line of code:
switch(choice) {
...
case 9:
...
for(int i = 0; i < rnd; i++) {
...
apdu.command[Apdu.P1] = (byte) (i * 100);
Unlike in your code for writing data to the card, here you are passing the data offset in P1 parameter. Please remember, that P1 is only one byte and it will overflow for i=3, so it is not possible to encode offsets of 638-bytes long array in P1.
The quickest solution of your problem is to use the same approach as in your writing code, i.e.:
switch(choice) {
...
case 9:
...
for(int i = 0; i < rnd; i++) {
...
apdu.command[Apdu.P1] = (byte) i;
and do the multiplication in the JavaCard code:
short o = (short) ((short) buffer[ISO7816.OFFSET_P1] * 100);
This solution should work, but it is not perfect as your JavaCard code supports arbitrary length of read/write (P2 - copy length), but offsets are fixed to 0, 100, 200 etc. It means that it works only as long as you send P2=100 to the card, which your present code does. But then why sending this parameter in the first place if it is fixed to one value?
I agree with Maarten Bodewes that it would be best to follow the ISO/IEC 7816-4 and use the command syntax specified there. UPDATE BINARY and READ BINARY commands described in the standard should fit your needs.

Arduino to Java data sent through USB

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

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.

Java Proxy Discovering Bot

I have written a class, ProxyFinder which connects to random ips and first pings them, and if they respond, attempts to create a http proxy connection through common proxy ports.
Currently, it is set up just connecting to random ips. This is relatively fast, discovering a few proxys an hour. However, I would like to somehow check if I have already previously connected to an ip. First I tried keeping them in a list, but that was using over 10GB of ram.. I included a method that I tried in the code below which writes the data to a cache using a RandomAccessFile, but this is incredibly slow to search through the entire file for each connection as it gets larger.
I am storing the data in as small of format as possible, simply four bytes for each ip. Even though, this is 4 * 256 * 256 *256 * 256 bytes.. = 16gb of raw ram.. or a 16gb file to search each time you want to test another ip.
I also tried creating a separate thread to generate ips, check them against the file, and then add them to a queue that the probe threads could pull from. It could not keep up with the probe threads either.
How can I quickly check if I have already connected to an IP or not, without being incredibly slow or using ridiculous amounts of memory?
package net;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* #author Colby
*/
public class ProxyFinder {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
int[] ports = {
1080, 3128, 3128, 8080
};
System.out.println("Starting network probe");
AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < 500; i++) {
new Thread(() -> {
do {
try {
byte[] addrBytes = randomAddress();//could be getNextAddress also
if (addrBytes == null) {
break;
}
InetAddress addr = InetAddress.getByAddress(addrBytes);
if (ping(addr)) {
float percent = (float) ((counter.get() / (256f * 256f * 256f * 256f)) * 100F);
if (counter.incrementAndGet() % 10000 == 0) {
System.out.println("Searching " + percent + "% network search");
}
for (int port : ports) {
try {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(addr, port));
HttpURLConnection con = (HttpURLConnection) new URL("http://google.com").openConnection(proxy);
con.setConnectTimeout(1000);
con.setReadTimeout(1000);
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.getContent();
con.disconnect();
System.out.println("Proxy found!" + addr.getHostAddress() + ":" + port + " Found at " + percent + "% network search");
} catch (Exception e) {
}
}
//
//System.out.println("Ping response: --" + addr.getHostAddress() + "-- Attempt: " + counter.get() + " Percent: " + percent + "%");
} else {
//System.out.println("Ping response failed: " + addr.getHostAddress() + " attempt " + counter.incrementAndGet());
}
} catch (Exception e) {
//e.printStackTrace();
}
} while (true);
}).start();
}
}
private static RandomAccessFile cache;
private static byte[] getNextAddress() throws Exception {
if (cache == null) {
cache = new RandomAccessFile(File.createTempFile("abc", ".tmp"), "rw");
}
byte[] check;
checkFile:
{
byte[] addr = new byte[4];
do {
check = randomAddress();
inner:
{
cache.seek(0);
while (cache.length() - cache.getFilePointer() > 0) {
cache.readFully(addr);
if (Arrays.equals(check, addr)) {
break inner;
}
}
cache.write(check);
break checkFile;
}
} while (true);
}
return check;
}
private static byte[] randomAddress() {
return new byte[]{(byte) (Math.random() * 256), (byte) (Math.random() * 256), (byte) (Math.random() * 256), (byte) (Math.random() * 256)};
}
private static boolean ping(InetAddress addr) throws Exception {
return addr.isReachable(500);
}
}
Also in case anyone is wondering, I've had this running for 12 hours now and it's discovered about 50 proxys, and pinged about 2.09664E-4% of the ip range which is about 1.2 million ips. not bad for the bandwidth allocated (0.5Mbps)
EDIT: I am starting to think that maybe the overhead of storing and checking all of these IPs would be even greater than simply connecting to many duplicates near the end of searching the ip range..
I would not store the whole IP address because of the amount of data. To store them in a array of BitSet would consume less memory.
edit previous code version removed, it was not correct
The version below generates random addresses and persist them in a file. If the persistence file of a previous run is found, the information of the seen addresses is restored from that file.
Following case was not handled correctly in the initial version:
assuming that no address was already seen
1.0.0.1 - seen false
2.0.0.2 - seen false
2.0.0.1 - seen true, which was wrong and is correctly handled by code below
See the comments in the code for further information.
public class KeepSeenAddresses {
static final int FILE_BUFFER_SIZE = 81_920;
static final int RANGES_SIZE = 256;
// to store 256 ranges of 255*255*255+1 addresses
static BitSet[] ranges;
// Random(1) is taken only for demonstration purpose, so the second
// application run will find the same seen addresses from previous run
static Random random = new Random(1);
// for normal use it's better to have better randomness
//static Random random = new Random(System.currentTimeMillis());
public static void main(String[] args)
throws IOException, ClassNotFoundException {
if (!readRanges()) {
initRanges();
}
// this case was failing in the initial solution
// uncomment this block to see how all edge cases
// which where mentioned in other comments are handled
/*
byte[][] addresses = {
{1, 0, 0, 1},
{2, 0, 0, 2},
{2, 0, 0, 1},
{1, 2, 3, 4},
{4, 3, 2, 1},
{(byte)128, 0, 0, 0},
{(byte)255, (byte)255, (byte)255, (byte)255}
};
seenAddress(addresses[0]);
seenAddress(addresses[1]);
seenAddress(addresses[3]);
seenAddress(addresses[5]);
seenAddress(addresses[6]);
for (byte[] addressBytes : addresses) {
System.out.printf("seen %s before: %s%n",
prettyAddress(addressBytes),
seenBefore(addressBytes)
);
}
*/
processAddresses();
persistRanges();
}
/**
* Read the seen addresses from a file.
*
* #return <code>true</code> if the file was found and has the expected
* number of ranges, otherwise <code>false</code>
* #throws IOException
* #throws ClassNotFoundException
*/
private static boolean readRanges() throws IOException, ClassNotFoundException {
File rangesStore = new File("addresses.bin");
if (!rangesStore.exists()) {
return false;
}
System.out.print("found previous rangesStore... ");
try (ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(rangesStore), FILE_BUFFER_SIZE
)
)) {
ranges = (BitSet[]) ois.readObject();
}
if (ranges.length != RANGES_SIZE) {
System.out.printf("wrong size of rangesStore: expected %d"
+ " found: %d%n", RANGES_SIZE, ranges.length);
return false;
} else {
System.out.printf("restored ranges: %d%n", ranges.length);
return true;
}
}
/**
* Initialize the address ranges array. All address flags will be set to
* <code>false</code>.
*/
private static void initRanges() {
System.out.print("initialize new rangesStore... ");
ranges = new BitSet[RANGES_SIZE];
for (int i = 0; i < RANGES_SIZE; i++) {
BitSet bitSet = new BitSet(255 * 255 * 255 + 1);
for (int j = 0; j < 255 * 255 * 255 + 1; j++) {
bitSet.clear(j);
}
ranges[i] = bitSet;
}
System.out.printf("initialized ranges: %d%n", RANGES_SIZE);
}
/**
* For demonstration purpose.<br>
* Generates some random IPv4 addresses. If the address was not seen before
* the flag for this address will be set to <code>true</code>.
*/
private static void processAddresses() {
for (int i = 0; i < 10; i++) {
byte[] addrBytes = randomAddress();
boolean seenBefore = seenBefore(addrBytes);
if (!seenBefore) {
seenAddress(addrBytes);
seenBefore = false;
}
System.out.printf("seen %s before: %s%n",
prettyAddress(addrBytes),
seenBefore
);
}
}
/**
* Persist the address ranges array. The file size is around 500MB.
*
* #throws IOException
*/
private static void persistRanges() throws IOException {
System.out.print("persist rangesStore... ");
try (ObjectOutputStream oos = new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream("addresses.bin"), FILE_BUFFER_SIZE)
)) {
oos.writeObject(ranges);
}
System.out.printf("written ranges: %d%n", ranges.length);
}
/**
* Keep a flag which address has been seen already.
*
* #param addrBytes IPv4 address in four bytes
*/
static void seenAddress(byte[] addrBytes) {
int rangeIndex = (int) addrBytes[0] & 0xff;
int rangeOffset = ((int) addrBytes[1] & 0xff * 0xffff)
+ ((int) addrBytes[2] & 0xff * 0xff)
+ ((int) addrBytes[3] & 0xff);
ranges[rangeIndex].set(rangeOffset);
}
/**
* Check if the passed address was seen before.
*
* #param addrBytes IPv4 address in four bytes
* #return <code>true</code> if the address was seen before, otherwise
* <code>false</code>
*/
static boolean seenBefore(byte[] addrBytes) {
int rangeIndex = (int) addrBytes[0] & 0xff;
int rangeOffset = ((int) addrBytes[1] & 0xff * 0xffff) + ((int) addrBytes[2] & 0xff * 0xff) + ((int) addrBytes[3] & 0xff);
return ranges[rangeIndex].get(rangeOffset);
}
/**
* Convert the IPv4 address into pretty string.
*
* #param addrBytes IPv4 address in four bytes
* #return pretty String of the IPv4 address
*/
static String prettyAddress(byte[] addrBytes) {
return String.format("%03d.%03d.%03d.%03d",
(int) addrBytes[0] & 0xff,
(int) addrBytes[1] & 0xff,
(int) addrBytes[2] & 0xff,
(int) addrBytes[3] & 0xff);
}
/**
* Generate a random IPv4 address.
*
* #return four bytes of a random generated IPv4 address
*/
private static byte[] randomAddress() {
byte[] bytes = new byte[4];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) random.nextInt(256);
}
return bytes;
}
}
I have ported code from another solution here to fit this problem:
Java- Mapping multi-dimensional arrays to single
The answer to the above question gives an in depth explanation of how the following code works. If anyone else would like to post a more in depth answer on this thread I will award it the answer.
static BitSet set;
static int pos(int i, int j, int k, int m) {
return ((256*256*256) * i) + ((256*256) * j) + (256 * k) + m;
}
static boolean get(byte[] addr) {
return set.get(pos(addr[0], addr[1], addr[2], addr[3]));
}
static void set(byte[] addr, boolean flag) {
set.set(pos(addr[0], addr[1], addr[2], addr[3]), flag);
}
Use a data base like MySql and hibernarte with level 1 & 2 cache.
It will be faster than RAM if u configure a cache with hibernate and tune ur db to use few gb of cache too. i think they all do. can configure an external cache like ehcahe when an be configured to live on another process + file with limits on size and time. Db knows how to index and seek things faster than even pure RAM - at such sizes as your IP
Plus you can improve by partitioning table data & index by first char, 2nd char etc

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');
}
}
}

Categories