I'm trying to get some values from rs232 (card reader Roger prt66lt) with a java simple serial connetor (jssc) but it look like i dont get any events started. I'm using the example code. The card reader is set to send card number when he reads it. But i dont get any event started coz i dont see event that System.out. I'm including jssc.jar (from 2.5.0 version) and its connecting to divice. Is this version of jssc doesnt need any .dll ? I think its included in it ? The similar code to this one but with RXTX library works fine but i need to include attahed dll library.
Card reader send me HEX value: 02, 10 chars DATA, 0D, 0A, 03
Code:
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
public class Main {
static SerialPort serialPort;
public static void main(String[] args) {
serialPort = new SerialPort("COM4");
try {
serialPort.openPort();//Open port
serialPort.setParams(9600, 8, 1, 0);//Set params
int mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR;//Prepare mask
serialPort.setEventsMask(mask);//Set mask
serialPort.addEventListener(new SerialPortReader());//Add SerialPortEventListener
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
static class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
System.out.println("Event started");
if(event.isRXCHAR()){//If data is available
if(event.getEventValue() == 10){//Check bytes count in the input buffer
//Read data, if 10 bytes available
try {
byte buffer[] = serialPort.readBytes(10);
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
else if(event.isCTS()){//If CTS line has changed state
if(event.getEventValue() == 1){//If line is ON
System.out.println("CTS - ON");
}
else {
System.out.println("CTS - OFF");
}
}
else if(event.isDSR()){///If DSR line has changed state
if(event.getEventValue() == 1){//If line is ON
System.out.println("DSR - ON");
}
else {
System.out.println("DSR - OFF");
}
}
}
}
}
The problem was that the default setting of RTS and DTR line is High so i need to use another setParams method and set the RTS line to false as needed by device.
Solution:
serialPort.setParams(9600, 8, 1, 0, false, true);
Related
Using Java, I'm trying to record sound from the default microphone and show the current volume and mute status (as set at OS level, not interested in checking bytes if possible). So far, I can get the TargetDataLine and record to it using the following code:
TargetDataLine line = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, formato));
This works great on Windows, line being the default microphone selected using the OS.
Right now, to get volume/mute controls I have the following code:
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
for (Mixer.Info mixerInfo : mixerInfos) {
Mixer mixer = AudioSystem.getMixer(mixerInfo);
if (mixer.getMaxLines(Port.Info.MICROPHONE) > 0) {
System.out.println("-------------");
System.out.println(mixerInfo);
Port line = (Port) mixer.getLine(Port.Info.MICROPHONE);
line.open();
Line.Info[] targets = mixer.getTargetLineInfo();
Control[] controls = line.getControls();
for (Control control : controls) {
if (control instanceof CompoundControl) {
Control[] subControls = ((CompoundControl) control).getMemberControls();
for (Control subControl : subControls) {
System.out.println(subControl);
}
} else {
System.out.println(control);
}
}
System.out.println("-----------");
}
}
There are 2 microphones in my setup and I haven't found a way of knowing which is the default one (right now it is the second one in the array).
Tried Line port = AudioSystem.getLine(Port.Info.MICROPHONE); and it is returning the first one available (and it is not the default in this instance).
So, any way to get the default microphone port that relates to the TargetDataLine obtained?
Thanks!
To get of all microphones installed in your system you can list them as follow :
package testing;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
public class Main {
public static void main(String[] args) {
//Enumerates all available microphones
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
for (Mixer.Info info: mixerInfos){
Mixer m = AudioSystem.getMixer(info);
Line.Info[] lineInfos = m.getTargetLineInfo();
if(lineInfos.length>=1 && lineInfos[0].getLineClass().equals(TargetDataLine.class)){//Only prints out info is it is a Microphone
System.out.println("Line Name: " + info.getName());//The name of the AudioDevice
System.out.println("Line Description: " + info.getDescription());//The type of audio device
for (Line.Info lineInfo:lineInfos){
System.out.println ("\t"+"---"+lineInfo);
Line line;
try {
line = m.getLine(lineInfo);
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
System.out.println("\t-----"+line);
}
}
}
}
}
Starting from that you can identify the default one...
For instance in my MacBook the default one has this name "Built-in Microphone"
I'm trying to read humidity and temperature data from an arduino board.
Currently it is outputting a simple integer caught by the bufferedreader and also the integer split to the temperature and humidity
Basically the output looks like this:
2021
20
21
2023
20
23
Running for a while, endlessly capturing the output of the arduino board and printing it out.
Here is the what the whole program looks like
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Serializable;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.util.Enumeration;
public class SerialTest implements SerialPortEventListener {
SerialPort serialPort;
/** The port we're normally going to use. */
private static final String PORT_NAMES[] = {
"/dev/tty.usbserial-A9007UX1", // Mac OS X
"/dev/ttyACM0", // Raspberry Pi
"/dev/ttyUSB0", // Linux
"COM5", // Windows
};
/**
* A BufferedReader which will be fed by a InputStreamReader
* converting the bytes into characters
* making the displayed results codepage independent
*/
private BufferedReader input;
/** The output stream to the port */
private OutputStream output;
/** Milliseconds to block while waiting for port open */
private static final int TIME_OUT = 2000;
/** Default bits per second for COM port. */
private static final int DATA_RATE = 9600;
public void initialize() {
// the next line is for Raspberry Pi and
// gets us into the while loop and was suggested here was suggested http://www.raspberrypi.org/phpBB3/viewtopic.php?f=81&t=32186
//System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyACM0");
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
/**
* This should be called when you stop using the port.
* This will prevent port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
/**
* Handle an event on the serial port. Read the data and print it.
*/
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
//output the BufferReader Input as Integer
int number = Integer.parseInt(input.readLine());
System.out.println(number);
//Separate the input at a integer into the temperature and humidity.
int Temp = number / 100;
int Humidity = number % 100;
System.out.println(Temp);
System.out.println(Humidity);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
public static void main(String[] args) throws Exception {
SerialTest main = new SerialTest();
main.initialize();
Thread t=new Thread() {
public void run() {
//the following line will keep this app alive for 1000 seconds,
//waiting for events to occur and responding to them (printing incoming messages to console).
try {Thread.sleep(1000000);} catch (InterruptedException ie) {}
}
};
t.start();
System.out.println("Started");
}
}
Here is the portion that handles an event and prints out the recieved information
/**
* Handle an event on the serial port. Read the data and print it.
*/
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
//output the BufferReader Input as Integer
int number = Integer.parseInt(input.readLine());
System.out.println(number);
//Separate the input at a integer into the temperature and humidity.
int Temp = number / 100;
int Humidity = number % 100;
System.out.println(Temp);
System.out.println(Humidity);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
Instead I would like to capture the temp and humidity into two separate arrays and incrementally build them till I can just print an array after capturing 10 outputs.
Honestly this is mostly borrowed code. It would be even better if I could have this entire class run inside another one, but I'm terribly new at this.
You need some place to store the collected numbers and print them when enough of them are received. Just add two member variables that are holding the data:
private List<Integer> temperatures = new ArrayList<>();
private List<Integer> humidities = new ArrayList<>();
Then collect and print them as follows:
temperatures.add(number / 100);
humidities.add(number % 100);
if(humidities.size() >= 10) {
System.out.println(temperatures);
System.out.println(humidities);
// clear both lists
temperatures.clear();
humidities.clear();
}
As a slight modification you can also use a single collection storing just the parsed numbers and do the temperature/humidity calculation when printing the numbers.
Im trying to make connection between my computer and arduino uno using Java Simple Serial Connector. Im trying to do it using code listed below. Somehow its not working ( the led diode connected to pin 7 of arduino is not turning on while running my programm, but when im using serial monitor of artuino software it does. ). Does anyone know why?
Java project code :
import jssc.SerialPort;
import jssc.SerialPortException;
public class Main {
public static void main(String[] args) {
//In the constructor pass the name of the port with which we work
SerialPort serialPort = new SerialPort("COM3");
try {
//Open port
serialPort.openPort();
//We expose the settings. You can also use this line - serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
//Writes data to port
serialPort.writeBytes("Test".getBytes());
//Closing the port
serialPort.closePort();
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
}`
Arduino code:
void setup() {
Serial.begin(9600); //Ustawienie prędkości transmisji
pinMode(7, OUTPUT);
digitalWrite(7, LOW);
}
void loop() {
if( Serial.available() > 0){
digitalWrite(7, HIGH);
}
}
I think, your Arduinocode is wrong.
I do it like this.
https://www.arduino.cc/en/Serial/Write
Serial.write(val)
Serial.write(str)
Serial.write(buf, len)
val: a value to send as a single byte
str: a string to send as a series of bytes
buf: an array to send as a series of bytes
len: the length of the buffer
I have modified the example shown on https://code.google.com/p/java-simple-serial-connector/wiki/jSSC_examples to show read/write from java program. I can run the program, however the data I send using serialPort.writeString("HelloWorld"); does not seem to be read in the SerialPortReader event class. Could any one please point what the issue is ?
public class SerialReaderWriter {
static SerialPort serialPort;
public static void main(String[] args) {
serialPort = new SerialPort("COM1");
try {
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
//Preparing a mask. In a mask, we need to specify the types of events that we want to track.
//Well, for example, we need to know what came some data, thus in the mask must have the
//following value: MASK_RXCHAR. If we, for example, still need to know about changes in states
//of lines CTS and DSR, the mask has to look like this: SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR
int mask = SerialPort.MASK_RXCHAR;
//Set the prepared mask
serialPort.setEventsMask(mask);
//Add an interface through which we will receive information about events
serialPort.addEventListener(new SerialPortReader());
serialPort.writeString("HelloWorld");
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
static class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
//Object type SerialPortEvent carries information about which event occurred and a value.
//For example, if the data came a method event.getEventValue() returns us the number of bytes in the input buffer.
System.out.println(event.getEventType());
if(event.isRXCHAR()){
if(event.getEventValue() == 10){
try {
String data= serialPort.readString();
System.out.println(data);
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
//If the CTS line status has changed, then the method event.getEventValue() returns 1 if the line is ON and 0 if it is OFF.
else if(event.isCTS()){
if(event.getEventValue() == 1){
System.out.println("CTS - ON");
}
else {
System.out.println("CTS - OFF");
}
}
else if(event.isDSR()){
if(event.getEventValue() == 1){
System.out.println("DSR - ON");
}
else {
System.out.println("DSR - OFF");
}
}
}
}
}
You can't read data from the same port where you write(COM1 here). I have followed the below steps for reading and writing using JSSC.
Fake your serial port with SerialPortMonitor.
Send data from COM2 from the SerialPortMonitor device installed.
Mode->Spy would show your written string "HelloWorld" and received String "OK"
Make the below modifications and check your code:
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN |
SerialPort.FLOWCONTROL_RTSCTS_OUT);
serialPort.writeBytes("HelloWorld");//Write data to port
PortReader portReader=new PortReader(serialPort)
serialPort.addEventListener(portReader, SerialPort.MASK_RXCHAR);
int[][] eventArray=serialPort.waitEvents()
for (int i = 0; i < eventArray.length; i++) {
if ((eventArray[i][0] > 0) ) {
serialPort.eventListener.serialEvent(new SerialPortEvent("COM1", eventArray[i][0], eventArray[i][1])); // wait for the listener event to complete
}
}
The port reader class: (You were missing the Override annotation and passing in the serial port)
public class PortReader implements SerialPortEventListener{
SerialPort serialPort
public PortReader(){}
public PortReader(SerialPort serialPort){this.serialPort=serialPort}
#Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR() && event.getEventValue() > 0) {
try {
String receivedData = this.serialPort.readString(event.getEventValue());
System.out.println("Received response: " + receivedData);
this.serialPort.closePort();//Close serial port
}
catch (SerialPortException ex) {
System.out.println("Error in receiving string from COM-port: " + ex);
this.serialPort.closePort();//Close serial port
}
}
}
}
The command
serialPort.writeString("HelloWorld");
sends the string
HelloWorld
from COM1. The SerialPortReader class that you are implementing causes COM1 to listen for the event type isRXCHAR (AKA when COM1 receives a char).
Do you have a serial cable connected to the serial port?
Unless you cross the RX and TX pins of COM1 or have a separate COM port (whose TX and RX is connected to COM1's RX and TX pins respectively), the SerialPortReader will never be activated.
if your device doesn't require RTS/CTS flow control
or you dont have a fully connected serial cable
( only RX, TX, GND)
you should switch off the data terminal ready (dtr)
signal for the serial communication
add this
serialPort.setRTS(false);
serialPort.setDTR(false);
after
serialPort.addEventListener(new SerialPortReader());
I am trying to make a strain gauge display numbers in my java interface.
I have the strain gauge circuit working, and it sends its voltage into a microcontroller (PIC16F877A) program to do an analog to digital conversion and then output the numbers on a serial port. If you are interested, here is the code:
unsigned short analog; //Variable for analog voltage
long tlong;
unsigned char ch; //
void main() {
USART_Init(19200); //set baude rate
ADCON1 = 0; //All PORTA pins as analog, VDD as Vref
TRISA = 0xFF; //All PORTA is input
do {
analog = ADC_Read(2) >> 2; //Read 10-bit ADC from AN2 and discard 2 LS bit
tlong = (long)analog * 5000; // Convert the result in millivolts
tlong = tlong / 1023; // 0..1023 -> 0-5000mV
ch = tlong / 1000; // Extract volts (thousands of millivolts) from result
USART_Write(48+ch); // Write result in ASCII format
USART_Write('.');
ch = (tlong / 100) % 10; // Extract hundreds of millivolts
USART_Write(48+ch); // Write result in ASCII format
ch = (tlong / 10) % 10; // Extract tens of millivolts
USART_Write(48+ch); // Write result in ASCII format
ch = tlong % 10; // Extract digits for millivolts
USART_Write(48+ch); // Write result in ASCII format
USART_Write(' ');
USART_Write(' ');
USART_Write(' ');
Delay_ms(1000);
} while (1);
}
That does not work perfectly, because as I move the strain gauge, the output numbers don't change the way that they should. If anyone has any ideas for that, it will be much appreciated.
But I moved on anyway and sent those numbers into my java program. I found this online and modified it to fit my design:
import java.io.*;
import java.util.*;
import gnu.io.*;
public class SimpleRead implements Runnable, SerialPortEventListener {
static CommPortIdentifier portId;
static Enumeration portList;
InputStream inputStream;
SerialPort serialPort;
Thread readThread;
static byte[] readBuffer;
public static int result2;
public static void main(String[] args) {
portList = CommPortIdentifier.getPortIdentifiers();
System.out.println("portList... " + portList);
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
System.out.println("port identified is Serial.. "
+ portId.getPortType());
if (portId.getName().equals("COM4")) {
System.out.println("port identified is COM4.. "
+ portId.getName());
// if (portId.getName().equals("/dev/term/a")) {
SimpleRead reader = new SimpleRead();
} else {
System.out.println("unable to open port");
}
}
}
}
public SimpleRead() {
try {
System.out.println("In SimpleRead() contructor");
serialPort = (SerialPort) portId.open("SimpleReadApp1111",500);
System.out.println(" Serial Port.. " + serialPort);
} catch (PortInUseException e) {
System.out.println("Port in use Exception");
}
try {
inputStream = serialPort.getInputStream();
System.out.println(" Input Stream... " + inputStream);
} catch (IOException e) {
System.out.println("IO Exception");
}
try {
serialPort.addEventListener(this);
} catch (TooManyListenersException e) {
System.out.println("Tooo many Listener exception");
}
serialPort.notifyOnDataAvailable(true);
try {
serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
// no handshaking or other flow control
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
// timer on any read of the serial port
serialPort.enableReceiveTimeout(500);
System.out.println("................");
} catch (UnsupportedCommOperationException e) {
System.out.println("UnSupported comm operation");
}
readThread = new Thread(this);
readThread.start();
}
public void run() {
try {
System.out.println("In run() function ");
Thread.sleep(500);
// System.out.println();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception in run() method");
}
}
public void serialEvent(SerialPortEvent event) {
// System.out.println("In Serial Event function().. " + event +
// event.getEventType());
switch (event.getEventType()) {
/*
* case SerialPortEvent.BI: case SerialPortEvent.OE: case
* SerialPortEvent.FE: case SerialPortEvent.PE: case SerialPortEvent.CD:
* case SerialPortEvent.CTS: case SerialPortEvent.DSR: case
* SerialPortEvent.RI: case SerialPortEvent.OUTPUT_BUFFER_EMPTY: break;
*/
case SerialPortEvent.DATA_AVAILABLE:
readBuffer = new byte[500];
try {
while (inputStream.available()>0) {
int numBytes = inputStream.read(readBuffer);
// System.out.println("Number of bytes read " + numBytes);
System.out.print(new String(readBuffer));
}
} catch (IOException e) {
System.out.println("IO Exception in SerialEvent()");
}
break;
}
// System.out.println();
/* String one = new String(readBuffer);
char two = one.charAt(0);
System.out.println("Character at three: " + two);*/
}
}
It reads the same range of numbers (one serial port, so I can't test if it's the same numbers) as the previous code, although it sometimes gives me weird numbers like instead of .692, it'll say 320, then the next number is 43, then maybe only a '.' will show up, but it will soon go back to normal. I assumed it was a buffer problem where it says "readBuffer = new byte[500]", where i changed the size to 500 (originally was 8) and it got slightly better.
I have to turn the output into an integer to do some math with it anyway, and as an integer I can easily filter out all the weird data. So ultimately, my question is now would I turn this output data into usable integers? The main problem is that I'm not even sure where in my java program it's reading the serial port numbers. I assume the variable is readBuffer, but I get errors when ever I try and use it places, usually a type mismatch.
So any help would be great, thanks!
I studied your above code further and I think in the above code the stream is:
<x.xxx >, so if you read 8 bytes each time that would be one data entry. If you use inputstreamreader if will convert byte to a character...
check http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStreamReader.html
It is hard to guess from info provided but You said:
"gives me weird numbers like instead of .692, it'll say 320"
and
The main problem is that I'm not even sure where in my java program it's reading the serial port numbers
This looks to me as byte order problem if you are trying to read Integer from received byte buffer. Also may be IEEE standard mismatch for float type if you try to read float data from received byte buffer. But I recommend to not use float types and use only integers.
if you are using java 5+ use ByteBuffer class from nio package, like this:
byte[] readBuffer = getBufferFromyourCode();
ByteBuffer buffer = ByteBuffer.wrap(readBuffer); //wrap received byte buffer
buffer.order(ByteOrder.LITTLE_ENDIAN);//set correct endiannes
Integer version = buffer.getInt();// read first 4 bytes
Integer length = buffer.getInt(); // read next 4 bytes
byte[] rowMsg = new byte[length];// length = bytes to read
buffer.get(rowMsg); // copies 'length' bytes in rowMsg
String msg = new String(rowMsg); // convert to String
System.out.println("Version "+version+" message received");
System.out.println("Length: "+length);
System.out.println("text: "+msg);
note byte order setting, try both big and little endian to see if values you read from buffer look normal.
Check more about endiannes here: http://en.wikipedia.org/wiki/Endiannes