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

kaisar Great
  • 111
  • 1
  • 5
  • 11

2 Answers2

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;
  ...
James Waldby - jwpat7
  • 8,800
  • 3
  • 16
  • 32
  • 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 03 '16 at 18:48
  • @kaisarGreat, see edit for working example – James Waldby - jwpat7 Nov 03 '16 at 19:23
  • Thank You Sir :D for your help and time :) @jwpat7 it really help me :D – kaisar Great Nov 03 '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 04: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 05:18
  • I did what you told sir @jwapat7 , I add 'case ',': val1=val; break' then in the both 'case 'a'' and 'b' I add 'Serial.println(val1);' and It works like a charm :) Thanks for your quick reply . – kaisar Great Nov 10 '16 at 15:46
  • Also, 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;` – James Waldby - jwpat7 Nov 10 '16 at 18:17
  • @kaisarGreat, please feel free to upvote answer – James Waldby - jwpat7 Nov 10 '16 at 18:18
  • Sir @jwpat7 I want to upvote your answer but my reputation is less 15 :D Thanks for the additional Information. – kaisar Great Nov 11 '16 at 12:45
  • Sir is it possible to save the value send example 200,400A .. then spilt 200 to val1 and 400 to val2 and save them into different variables but remains when the power of arduino is put out . – kaisar Great May 07 '17 at 17:25
  • @kaisarGreat, you could write a `recordData()` function, that when called will write indicated data to EEPROM if the value has changed. In `setup()`, load data from where you stored it. For data validation, you can store in cell after a value v its complement, ~v; if you load data and it fails the validation test, then write a default value to EEPROM. – James Waldby - jwpat7 May 07 '17 at 18:43
  • I used the above code you give and add some inside the case here is for `case a :` `WATEREQFORN1 = val; EEPROM.put(0, WATEREQFORN1);` `case b :` `WATEREQFORN2 = val; EEPROM.put(1, WATEREQFORN2);` `case d :` `DELAY = val; EEPROM.put(3, DELAY);` but when i change the value of `A` , then change the value of `B` the value on `A` will also change in random numbers .. how could i achieve writing into eeprom without changing some that i already save in there .. – kaisar Great May 08 '17 at 12:30
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.

Zukaberg
  • 101