I am making a device which can multiply the analog input signal with respect to the selected gain from the digital inputs. Here I have used two digital inputs(from which I can have four selections) but I am planing to add two inputs more(then I can have 16 selections). I made the code with if else statements is there any shorter way to do that? or else the code is getting huge.
here is the code:
#define sensor A0
#define resetPin 3
#define measurePin 2
#define k1 3
#define k2 4
float A = 0;
float J = 0;
int resetstatus = 0;
int measurestatus = 0;
void setup() {
Serial.begin(9600);
pinMode(sensor,INPUT);
pinMode(resetPin,INPUT_PULLUP);
pinMode(measurePin,INPUT_PULLUP);
pinMode(k1,INPUT_PULLUP);
pinMode(k2,INPUT_PULLUP);
Serial.println("INITIALAIZING");
delay(3000);
Serial.println("Ready to begin");
delay(200);
}
void loop()
{
resetstatus = digitalRead(resetPin);
measurestatus = digitalRead(measurePin);
if(resetstatus == LOW)
{
reset();
delay(200);
}
if(measurestatus == LOW)
{
if(digitalRead(k1 == LOW) && digitalRead(k2 == LOW))
{
J = 1.0;
measure();
delay(50);
}
else if(digitalRead(k1 == LOW) && digitalRead(k2 == HIGH))
{
J = 2.0;
measure();
delay(50);
}
else if(digitalRead(k1 == HIGH) && digitalRead(k2 == LOW))
{
J = 3.0;
measure();
delay(50);
}
if(digitalRead(k1 == HIGH) && digitalRead(k2 == HIGH))
{
J = 4.0;
measure();
delay(50);
}
}
}
void measure()
{
A = analogRead(sensor);
float sumA = A * J;
Serial.println(sumA);
}
void reset()
{
Serial.println("reset");
}
I am having a problem with the output from this code (I am using a potentiometer to feed the arduino an analog value)
I dont know why the output is showing 993 and 3972 at each cycle. can someone explain?
4 Answers 4
I made the code with if else statements is there any shorter way to do that?
j = 1 + (digitalRead(k1) | (digitalRead(k2) << 1) | (digitalRead(k3) << 2) | (digitalRead(k3) << 3));
or
j = 1 + digitalRead(k1) + 2*digitalRead(k2) + 4*digitalRead(k3) + 8*digitalRead(k4)
dont know why the output is showing 993 and 3972 at each cycle. can someone explain?
the printed values are off because of the error addressed in Nick's answer
-
If
k1 = 0
,k2 = 1
the original code selects2.0
, but your code computes3.0
. Ifk1
andk2
were switched it would be right. However, for more general values a lookup table or array for theJ
values should be used.Maximilian Gerhardt– Maximilian Gerhardt2018年06月07日 09:31:30 +00:00Commented Jun 7, 2018 at 9:31 -
@MaximilianGerhardt, it is no importand which kx is which button. it would be strange if I switch k1 and k2 in the formula2018年06月07日 09:45:30 +00:00Commented Jun 7, 2018 at 9:45
This is wrong:
if(digitalRead(k1 == LOW)
You mean:
if(digitalRead(k1) == LOW
Ditto for a lot of other places in your code.
I made the code with if else statements is there any shorter way to do that? or else the code is getting huge.
Yes, there is a way of simplification. As @Juraj already noted, it can in this special case even be expressed as a binary representation:
if(digitalRead(k1) == LOW && digitalRead(k2) == LOW)
{
J = 1.0;
measure();
delay(50);
}
else if(digitalRead(k1) == LOW && digitalRead(k2) == HIGH)
{
J = 2.0;
measure();
delay(50);
}
else if(digitalRead(k1) == HIGH && digitalRead(k2) == LOW)
{
J = 3.0;
measure();
delay(50);
}
if(digitalRead(k1) == HIGH && digitalRead(k2) == HIGH)
{
J = 4.0;
measure();
delay(50);
}
What you are doing here is the following pattern:
- read the state of the buttons
- depending on which combinations of buttons is pressed, assign a different value to
J
We can generalize this concept of "get the J value for a certain button combination" by doing the following:
- aggregate the entire "button states" into a single, unique number
- search for the associated
J
value
If we name the input button states "k1" and "k2", we see that you have the following logic:
| k1 | k2 | J |
| 0 | 0 | 1.0 |
| 0 | 1 | 2.0 |
| 1 | 0 | 3.0 |
| 1 | 1 | 4.0 |
We simply concatenate the button inputs to a signle bitstring "k1|k2" and we see
| (k1,k2) | J |
| 00 | 1.0 |
| 01 | 2.0 |
| 10 | 3.0 |
| 11 | 4.0 |
If we re-write the binary indices to decimal numbers:
| (k1,k2) | J |
| 0 | 1.0 |
| 1 | 2.0 |
| 2 | 3.0 |
| 3 | 4.0 |
So we see that we can use this (k1,k2) number as an index from 0 to 3 to get us a J value as such:
//Aggregate all button inputs to single number
//using bitshifts
int index = (digitalRead(k2) << 1) | digitalRead(k1);
//All used J values in the right order
const float J_values[] = {
1.0f, 2.0f, 3.0f, 4.0f
};
//get the right J value
J = J_values[index];
//measure and delay
measure();
delay(50);
This replaces all your 4 if-else
statements and does exactly the same.
Now if you were to add more inputs, you can simply expand the way you construct the index number and your J_values
array. Write down the "function table" for your wanted J
values as above, construct the bit strings, order the indices in ascending order and write down the array values accordingly.
Referenecs:
Put all 4 pins on one port then do a port read. Say you used D2,3,4,5 Then switches = (PIND && 0b00111100)>> 2;
then switches = 0 to 15 and you can do a branch on that.
-
yes +1, this low level solution should be mentioned here as answer too2018年06月08日 17:41:14 +00:00Commented Jun 8, 2018 at 17:41