1

I have a project in arduino that i interface with java. The arduino is connected to the computer via usb cable , I use the serial communication. I have two variables:

//Code in arduino
int ADelay = 1000;
int BDelay = 1000;

I want to change the value of each variable based on the input of the user using the java interface. Is there a code that let the arduino identify that this data:

2000

Is intended to or for:

int ADelay

and this

300

is for

int BDelay

My only idea on how to achieve this is to add A or B before the number before i send to arduino

A2000
B300

And use Delimeter in arduino to split the data and use if else condition to decide where the data belong , Is there any other way ? Thanks

  • 1
    And how has that failed you? – Ignacio Vazquez-Abrams Nov 3 '16 at 17:40
  • I want to know if my idea is right or is there other simple way to do it :D – kaisar Great Nov 3 '16 at 17:45
  • how often do you need to poll the data? – Zukaberg Nov 3 '16 at 17:53
  • It depends , but maybe twice is the maximum . – kaisar Great Nov 3 '16 at 18:01
0

The approach noted in the question – having an identifying character at the front of each number – is a workable approach. Other approaches include:
• always sending numbers in pairs, eg 2000,300 would denote A2000 B300.
• encoding the A or B as part of the number; eg, the range 0-4999 could denote A delays of 0 to 4999, while the range 5000-9999 could denote B delays of 0 to 4999.
• sending A delays via decimal digits, and B delays via letter-substitutes for digits; eg DAA could encode a B delay of 300.

One of the easiest-to-parse approaches is to have an identifying character at the end of each number, rather than at the front. This allows your code to pick up digits until a letter appears, and then dispatch based on the letter. Here's some example code:

// Sketch that accepts numbers and action code via serial input.
// Silently ignores any numbers not followed by a valid action letter.
// Does not test for number overflow.      - jiw 3 Nov 2016

void setup() {
  Serial.begin(115200);         // init serial port
}

unsigned int val=0;
void loop() {
  char inc;
  while (Serial.available()) { // Get characters
    inc = Serial.read();
    if (inc >= '0' && inc <= '9') {
      val = 10*val + (inc-'0');
    } else {
      switch (toupper(inc)) {
      case 'A':
        Serial.print("Case A got ");
        Serial.println(val);
        break;
      case 'B':
        Serial.print("Case B got ");
        Serial.println(val);
        break;
      default :
        ; // handle blanks, returns, etc
      }
      val = 0;  // Set val to zero after any non-digit
    }
  }
}

Edit 2: This edit incorporates some code suggestions from comments into the answer.


If you need to know whether a number for val1 has been specified -- that is, if you handle items like 500B as well as 300,500B -- you can set/test/clear a flag:

...
case ',':
  val1=val; v1flag=1;
  break;
...
case 'B':
  if (!v1flag) val1=val1default;
  Serial.print("B stuff with val and val1");
  v1flag=0;
  break;
...

To retain when the power is off, you can write a recordData() function, that when called will write selected data to EEPROM if the value has changed. In setup(), load data from where you stored it. For data validation, you can store in the cell after a value v its complement, ~v. If when you reload data it fails the validation test, use a default value instead, and write it to EEPROM for future use.


The code snippet shown next, from kaisarGreat's 8 May comment, has several problems to be corrected:

case a : 
  WATEREQFORN1 = val;
  EEPROM.put(0, WATEREQFORN1);
case b : 
  WATEREQFORN2 = val;
  EEPROM.put(1, WATEREQFORN2); 
case d :
  DELAY = val;
  EEPROM.put(3, DELAY);

Logic or syntax problem: Missing break statements at ends of cases. This error will allow execution to flow from one case into the next. While there are situations where that's useful, this is not one.

Logic or syntax problem: Unless a, b, ... are declared constants they won't work as case designators. Perhaps use 'A', 'B', ... instead.

Style problem: Variable names in all upper case. Conventionally, C and C++ programmers use all-upper-case names to designate defined constants or macros. Contravening that convention can lead to confusion if other people use or maintain the code. Instead of WATEREQFORN1 consider waterEq1.

Allocation problem: Presumably the WATEREQ... variables are multiple bytes in length. EEPROM.get() and put() read and write data types with multiple bytes using several consecutive bytes of EEPROM. For example, if WATEREQFORN1 is a real and takes 4 bytes, it will occupy cells 0, 1, 2, 3 in EEPROM.

The following code snippet fixes some of those problems.

enum { WaterAddr1=0, WaterAddr2=WaterAddr1+sizeof waterEq1, DelayAddr=WaterAddr2+sizeof waterEq2 };
...
case 'A': 
  waterEq1 = val;
  EEPROM.put(WaterAddr1, waterEq1);
  break;
case 'B': 
  waterEq2 = val;
  EEPROM.put(WaterAddr2, waterEq2); 
  break;
case 'D':
  Delay = val;
  EEPROM.put(DelayAddr, Delay);
  break;
  ...
  • Can you give me a code snippet C programing language on how to pick up digits until a letter appears and make an if else condition based on the letter :D Thanks a lot – kaisar Great Nov 3 '16 at 18:48
  • @kaisarGreat, see edit for working example – James Waldby - jwpat7 Nov 3 '16 at 19:23
  • Thank You Sir :D for your help and time :) @jwpat7 it really help me :D – kaisar Great Nov 3 '16 at 19:28
  • Sir @jwpat7 is it posible to combine the snippet code above you give and one approach you give the sending numbers in pair ? Example I will send 200A300 or 200,300A then put them in separate varables .. 200B300 or 200,300B .. – kaisar Great Nov 10 '16 at 4:36
  • Yes, you can do that, but handling numbers in pairs complicates the parsing – it's simpler and easier to handle independent values. ¶ That said, one approach is to add case ',': val1=val; break; into the switch, and then when you get the A or B (for a form like 200,300A or 200,300B) do an action using both val1 and val. That is, the action for the comma case stores a value for future use; while letter cases can use two vals. – James Waldby - jwpat7 Nov 10 '16 at 5:18
0

If you are just looking to send something as simple as 2 integers, your approach should be fine, you just need to set your own protocol to encode the data from java and decode it on the arduino side.

Another easy way would be to set a starting byte, could be anything like 0x6A etc, (with optional checksum if it's through bluetooth or other noisy communication method):

[8 bit starting byte][32 bit integer data A][32 bit integer data B]

On the arduino side you want to keep polling for the starting byte, once you receive the special byte then the next 32 bits would be your data A and the following 32 bits would be your data B.

However if you want something more robust or object oriented you could look into this library: https://github.com/bblanchon/ArduinoJson

It allows you to decode and encode JSON objects which is very flexible and widely accepted, so you just need to encode the data into a JSON object on the java side and decode it using that library.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.