0

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)

output

I dont know why the output is showing 993 and 3972 at each cycle. can someone explain?

2

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 selects 2.0, but your code computes 3.0. If k1 and k2 were switched it would be right. However, for more general values a lookup table or array for the J values should be used. – Maximilian Gerhardt Jun 7 '18 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 formula – Juraj Jun 7 '18 at 9:45
3

This is wrong:

if(digitalRead(k1 == LOW)

You mean:

if(digitalRead(k1) == LOW

Ditto for a lot of other places in your code.

2

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:

1

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 too – Juraj Jun 8 '18 at 17:41

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.