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
-
1And how has that failed you?Ignacio Vazquez-Abrams– Ignacio Vazquez-Abrams2016年11月03日 17:40:33 +00:00Commented Nov 3, 2016 at 17:40
-
I want to know if my idea is right or is there other simple way to do it :Dkaisar Great– kaisar Great2016年11月03日 17:45:57 +00:00Commented Nov 3, 2016 at 17:45
-
how often do you need to poll the data?Zukaberg– Zukaberg2016年11月03日 17:53:43 +00:00Commented Nov 3, 2016 at 17:53
-
It depends , but maybe twice is the maximum .kaisar Great– kaisar Great2016年11月03日 18:01:29 +00:00Commented Nov 3, 2016 at 18:01
2 Answers 2
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 lotkaisar Great– kaisar Great2016年11月03日 18:48:17 +00:00Commented Nov 3, 2016 at 18:48
-
@kaisarGreat, see edit for working exampleJames Waldby - jwpat7– James Waldby - jwpat72016年11月03日 19:23:37 +00:00Commented Nov 3, 2016 at 19:23
-
Thank You Sir :D for your help and time :) @jwpat7 it really help me :Dkaisar Great– kaisar Great2016年11月03日 19:28:29 +00:00Commented Nov 3, 2016 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– kaisar Great2016年11月10日 04:36:35 +00:00Commented Nov 10, 2016 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 theswitch
, and then when you get the A or B (for a form like200,300A
or200,300B
) do an action using bothval1
andval
. That is, the action for the comma case stores a value for future use; while letter cases can use two vals.James Waldby - jwpat7– James Waldby - jwpat72016年11月10日 05:18:01 +00:00Commented Nov 10, 2016 at 5:18
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.