jSerialComm: Java to arduino, not the same data.

Hello everyone :slight_smile: ,

i am working on a project in internship and i have some issues for trying to cummunicate a Java Programme to a Arduino Mega 2560 while using the librairie jSerialComm. I use the usb cable to connect the arduino.

Here the things, I send the data to the card by the port: /dev/cu.usbmodem1411, but everytime i send a number (for example: 1) in the arduino it's never the same number. The goal of sending data to the arduino is for typing a led number in java to make it light in arduino with of course Serial. I want also to send word to the arduino.

If i send 1, it will light the led number one.
If i type "test", il will light all the led.

For any member of this forum who have worked with jSerialcomm or any other java library better then RxTx to communicate with the arduino. how do you send the same data to your arduino? why it work with the Serial monitor but not with my java programm? what does the Serial monitor really send to the arduino?

I have already checked a lot of topic but none of them work for me...

My project is divided in two parts: Java part using Sockets and Arduino part...
I communicate with the Serveur_trie.java file to the arduino

The Server java file:

package server;

import cheque.Cheque;

import java.util.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.net.*;

import com.fazecast.jSerialComm.*;

public class Serveur_trie extends Thread
{
    String name; // nom du client connecté au thread serveur
    Socket clientSocket;
    ObjectOutputStream out;
    private static HashMap<String, Serveur_trie> tableau_nom = new HashMap<String, Serveur_trie>(); // stocke les noms d'utilisateurs dans un tableau



    private int algorithme_trie(int num_donnee) // permet de trouver la case pour trier le cheque
    {
        return num_donnee;
    }

    private void display_port()
    {
        SerialPort[] ports = SerialPort.getCommPorts();
        for (int i = 0; i < ports.length; i++) 
        {
        System.out.println(ports[i].getSystemPortName());
        }
    }

    private void envoie_donnee_arduino(Integer num_led) throws Exception 
    // permet d'envoyer les données de l'algorithme à la partie Arduino13
    {
        display_port();
        SerialPort sp = SerialPort.getCommPort("/dev/cu.usbmodem1411"); // port  arduino Mega 2650
        System.out.println(sp.getDescriptivePortName());
        sp.setComPortParameters(9600, 8, 1, 0); // default connection settings for Arduino
        sp.setComPortTimeouts(SerialPort.TIMEOUT_WRITE_BLOCKING, 0, 0); // block until bytes can be written
        
        if (sp.openPort())
        {
            System.out.println("Port is open");
        }
        else 
        {
            System.out.println("Failed to open port");
            return;
        }

        sp.addDataListener(new SerialPortDataListener()  
        {
            @Override
            public int getListeningEvents() {
                return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
            }

            @Override
            public void serialEvent(SerialPortEvent event) {
                if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
                    return;
                }
                byte[] newData = new byte[sp.bytesAvailable()];
                int numRead = sp.readBytes(newData, newData.length);
                System.out.println("Read " + numRead + " bytes. " + newData[0]);
            }
        });
        
        Thread.sleep(2000);
        byte[] writeBuffer = Integer.toString(num_led).getBytes(StandardCharsets.UTF_8);
        //char test = Character.forDigit(num_led, 10);
        System.out.println("byte value = " + writeBuffer[0]);
        sp.getOutputStream().write(num_led); // écrit les données en BYTE du serveur vers le port
        sp.getOutputStream().flush(); 
          
        if (sp.closePort())
        {
            System.out.println("Port is closed :)");
        } 
        else 
        {
            System.out.println("Failed to close port :(");
            return;
          
        }

    }

    public void run() // fonction du thread
    {

        try (
 ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
 ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
        )
        {
            while(true)
            {
                Object o = in.readObject();
                if (o instanceof Cheque)
                {
                    Cheque cheque = (Cheque) o;
                    System.out.println("info: " + cheque.get_Num_case());
                    envoie_donnee_arduino(algorithme_trie(cheque.get_Num_case()));
                }
            }
           /* else 
            if(o instanceof String) 
            {
                if( ((String) o).equals("BYE") )
                {
                    break;
                }
            }*/
        }
        catch (IOException e)
        {
            System.err.println("Exception while closing connection!");
        }
        catch (Exception e)
        {

        }

    }

    public Serveur_trie(Socket clientSocket)
    {
        this.clientSocket = clientSocket;
    }

    public static void main(String[] args) throws IOException
    {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Bienvenue au serveur, Veillez saisir...");
        System.out.println("Votre numéro de port >"); 
        int num_port = scanner.nextInt(); // on enregistre le numéro du

        try (
        ServerSocket serverSocket = new ServerSocket(num_port); 
        )
        {
            while (true)
            {
                Serveur_trie server = new Serveur_trie(serverSocket.accept()); 
                System.out.println("Client connecté");
                server.start();
            }
        }
        catch (IOException e)
        {
            System.err.println("Exception caught when trying to listen on port " + num_port);
            System.err.println(e.getMessage());
        }
        System.out.println("fermeture du serveur");
        scanner.close();

    }
}

The arduino file:

#include <Wire.h>
#include <stdio.h>

const int ref_pin = 2;
const int LIM_TAB = 5;

char tab_carac[LIM_TAB];
boolean newData = false;

void all_led(int dep_led)
{
  for (int i = 0 ; i <= 4 ; i++)
  {
    for (int i = ref_pin; i < ref_pin + 10 ; i++)
    {
      digitalWrite(i,LOW);
    }
    delay(1000);
  
    for (int i = ref_pin; i < ref_pin + 10  ; i++)
    {
      digitalWrite(i,HIGH);
    }
    delay(1000);
  }
}

boolean is_a_number(int n)
{
  return n >= 48 && n <= 57;
}

int ascii2int(int n, int byte_read)
{
  return n*10 + (byte_read - 48);
  
}


/*int concat(int a, int b) 
{ 
  
    char s1[20]; 
    char s2[20]; 
  
    // Convert both the integers to string 
    sprintf(s1, "%d", a); 
    sprintf(s2, "%d", b); 
  
    // Concatenate both strings 
    strcat(s1, s2); 
  
    // Convert the concatenated string 
    // to integer 
    int c = atoi(s1); 
  
    // return the formed integer 
    return c; 
}*/

boolean is_test(char tab[])
{
  
  if (strncmp(tab,"test",4) == 0)
  {
    return true;
  }
  else
  {
    return false;
  }
}


//-------------------------------------------------------------------

void setup() 
{
  // put your setup code here, to run once:
  for (int i = ref_pin; i < ref_pin + 10 ; i++)
  {
    pinMode(i,OUTPUT);
    digitalWrite(i,HIGH); // LED OFF
    delay(2);
  }
  
  Serial.begin(9600);
  while (!Serial) 
  {
    ; // wait for serial port to connect.
  }
  Serial.print("Pin ready!");
}



void loop() 
{
  collectDataFromJava();
  DataLightLED();
  memset(tab_carac,0,sizeof(tab_carac));
  newData = false;

}


void collectDataFromJava()
{
  int ndx = 0;
  
  while (newData == false)
  {
    
    while (Serial.available() > 0)
    {
        byte byte_read = Serial.read();
        if (byte_read != '\n')
        {
          tab_carac[ndx] = byte_read;
          ndx++;
        }
        else
        {
          tab_carac[ndx] = '\0';
          ndx = 0;
          newData = true;
        }
        
    }
  }
}

void DataLightLED()
{
  if (tab_carac[0] != '\0')
  {
    
    if(is_test(tab_carac) == true)
    {
      all_led(ref_pin);
    }
    else
    {
      int pin_a_allumer = 0;
      for (int b = 0; b < sizeof(tab_carac) ; b++)
      {
        if (is_a_number(tab_carac[b]))
        {
          pin_a_allumer = 10*(pin_a_allumer) + (ascii2int(0,tab_carac[b]));
        }
      }
      digitalWrite(pin_a_allumer + 1,LOW); // LED OFF

      
    }
  }
}

Thanks in advance for your response.

how have you wired things ?

Serial is point to point communication. You can't have the Serial Console open for your Arduino and at the same time the Java program talking through USB to your MEGA. that would be 3 participants on the Serial line.

when you try on the Serial Monitor, then it's only 2 participants that's why it works.

Your MEGA has other Serial ports, hook up a FTDI and have your Java program send data there or don't open the Arduino Serial monitor and write a bit of code in Java that prints what the Arduino is sending back.

Hi, thank for your response.

I know that i can't have the Serial Monitor and the Java programm at the same time, it would never open the port then...

I just can't figure out why, when i do a Java-Arduino communication with jSerialComm, I never get the correct data.

I started to programm the Arduino code with the Serial Monitor first, to be ready with the Java programm but it don't work...

Also when i try to read what the Arduino have really recieved, the DataListener seem to do read everything so i can't check witch is the correct data from Java that the arduino has recieved

I started to programm the Arduino code with the Serial Monitor first, to be ready with the Java programm but it doesn't work...

well then you should fix that....

but really keep thinks super simple.

write a Java code that sends HELLO to the Serial line and printing what it gets back.

write a C++ code listening to the Serial port and just echoing what it gets

as long as you don't get that to work, there is no point messing around with the rest of your code.
When that works, then build upon it.

And remember about endianness and size if you deal with numbers

I write it wrong, the Arduino code work perfectly with the Serial Monitor.
The problem is that i can figure out what I need to do to make my Java programm send the data to the Arduino and make the arduino receive the correct data...

The same way I do with my Serial Monitor...

Swaggydogy:
My project is divided in two parts: Java part using Sockets and Arduino part...
I communicate with the Serveur_trie.java file to the arduino

I can't make sense of the Java code. It always seems to me that Java code is deliberately written so that non-Java programmers can't make sense of it. I did use JRuby regularly some years back with the JSSC library for communication with my Arduinos. I did post some code here but, sorry, I can't find it now.

Is your Java code opening and closing the serial port for every message? It should not. It should open the serial port, allow time for the Arduino to reset before sending any data and then keep the serial port open until it is completely finished with the Arduino. This Simple Python - Arduino demo illustrates how I do it now with Python. My JRuby code was essentially equivalent.

Separately, your Arduino code seems to derive from my Serial Input Basics and, of course, you are free to use it any way you wish. However when you are seeking help here it makes things much easier if you use the tutorial code without any changes.

...R

The things is i can't figure out what the arduino is recieving, the dataListener in the Serialport trigger before sending the data to arduino.

This is what happen

For the future please make your images visible here. See this Simple Image Posting Guide.

Even better, don't post images of text, just copy and paste the text.

I can't make sense of the text in your image but I see "Port is open" shortly followed by "Port is closed" and that worries me.

It's a good idea to include in your PC program the ability to display Arduino debug messages. They could, for example, be Serial.print() messages that begin with the characters "Dbg". E.G.. Serial.println("Dbg This is a debug message"). That way your PC program can separate the debug messages from the "proper" data.

...R

ok here is the arduino code:

void loop() 
{
  Serial.print("Debug");
  collectDataFromJava();
  DataLightLED();
  memset(tab_carac,0,sizeof(tab_carac)); // on vide le tableau
  newData = false; // on remet à zéro puisque on lit une nouvelle donnée

}


void collectDataFromJava()
{
  int ndx = 0;
  
  while (newData == false)
  {
    
    while (Serial.available() > 0) // tant que il reste des données à traiter et que on a pas fini de remplir tous les cases du tableau 
    {
        byte byte_read = Serial.read();
        Serial.print(byte_read);
        if (byte_read != '\n')
        {
          tab_carac[ndx] = byte_read;
          Serial.print(tab_carac[ndx]);
          ndx++;
        }
        else
        {
          tab_carac[ndx] = '\0';
          ndx = 0;
          newData = true;
        }
        
    }
  }
}

void DataLightLED()
{
  if (tab_carac[0] != '\0') // si on a fini d'avoir toutes les données envoyé depuis le Serial.
  {
    
    if(is_test(tab_carac) == true)
    {
      all_led(ref_pin);
    }
    else
    {
      int pin_a_allumer = 0;
      for (int b = 0; b < sizeof(tab_carac) ; b++)
      {
        if (is_a_number(tab_carac[b]))
        {
          pin_a_allumer = 10*(pin_a_allumer) + (ascii2int(0,tab_carac[b]));
        }
      }
      digitalWrite(pin_a_allumer + 1,LOW); // LED OFF

      
    }
  }
}

I have managed to send message from arduino to java...
When i try to send a number from java to arduino like 2:
Here the result:

Port is open
DATA FROM ARDUINO: Deb
DATA FROM ARDUINO: ug
byte value = 50
DATA FROM ARDUINO: 130
Port is closed :slight_smile:

why does it put a random number in arduino after sending the data?

your arduino program is not complete - missing setup and variable definitions and You are at risk of overflowing your tab_carac array as you don't test for bounds.

Swaggydogy:
why does it put a random number in arduino after sending the data?

That seems like a Java question rather than an Arduino question.

...R

print sends the ASCII version back of whatever you received. write would send the numerical value of the byte

I have made my programm with the Serial monitor first and it work perfectly.

Do you know what the Serial monitor is really sending to the arduino when i enter in the Serial monitor?
Byte? Char? Int?

J-M-L:
print sends the ASCII version back of whatever you received. write would send the numerical value of the byte

What do you mean by that?
I send by java using this:

sp.getOutputStream().write(num_led.byteValue());

and i read the data in Arduino using this:

byte byte_read = Serial.read();

Does that mean my java send int value and the arduino read the ascii value?

On the Arduino side, let's say you have a byte with a value of 49(dec)

byte b = 49;

if you do aSerial.print(b);that will display 49. It means two bytes are sent over the Serial line, one for the ASCII code of '4' and the other for the ASCII code of '9'. The Serial line will thus carry two bytes 52(dec) and 57(dec).
if instead of the Serial monitor you have a Java program on the other side, it will get those 2 bytes.

if you do aSerial.write(b);then only one byte (value 49(dec)) is sent over the Serial line, and because the value 49(dec) is the ascii code of '1' and the Serial monitor always interprets what comes as ASCII (UTF8 actually) you will then see '1' in the Serial monitor.

makes sense ?

See asciitable.com for the complete list.

We were trying to receive info from Sparkfun fingerprint scanner, kept getting U, or 87, when we were expecting to see 0x55. Had to adjust format of received data so the numbers made sense.
And for AA you get a non-printable ASCII character (decimal 170), so that didn't help.

yeah, but do you have any clue why does my arduino print random number instead.
I admit that sometime when i tape 2 for exemple, it does actually print the ascii code of 50 so 2...
But it is never regular, i get 2, 2 but then 13, 225...

Swaggydogy:
I send by java using this:

sp.getOutputStream().write(num_led.byteValue());

You have to tell us what is the type and the content of the variable num_led and what is produced by led.byteValue()

If the variable num_led is a 16 bit integer and contains (say) the value 65 and if the byteValue() method converts that to an 8 bit value also containing 65 then your Arduino code should receive the byte value of 65. Unless of course sp.getOutputStream().write() adds some other stuff.

I seem to recall from when I was using JRuby that Java treated bytes as signed values (the equivalent of char in Arduino code) but I can't remember what I needed to do to get around that. Maybe that is an issue for you to study.

I find it makes debugging much simpler to send data as human readable text and if you do that the examples in Serial Input Basics will be useful.

...R

PS ... referring to Reply #15, have you taken the precaution, in your Arduino code, to make sure you read all of the values that might be in the Serial Input Buffer? If you see a value of 13 it strongly suggests that a carriage-return character was sent

You have to tell us what is the type and the content of the variable num_led and what is produced by led.byteValue()

The variable num_led in Java is a integer number who is send by the client socket, the server receive the message and the led.byteValue() convert the data in byte.

But when i thinking of this, my arduino programm light the LED only if he detect the new line character (\n)
Maybe i need to send to the arduino this character also maybe it can work

Simplify your code to just bare bone use case

You send ONE int in java using your write() command in Java
You echo what you get on the Arduino side back to java using write
You print in java what’s echoed both in ASCII and binary to see what’s going on

Swaggydogy:
The variable num_led in Java is a integer number who is send by the client socket, the server receive the message and the led.byteValue() convert the data in byte.

You need to identify for us what Java considers an integer to be and what it considers a byte to be. They may not be the same definitions as in an C++ for an Arduino.

Plus what @J-M-L has said

...R