Conditional in digitalWrite()?

Hello, I’m pretty new to any C style language, and Arduinos as well…

I’m wondering if there’s a neater way of doing this

if <true> {
digitalWrite(pinNumber, HIGH);
}
else{
digitalWrite(pinNumber, LOW);
}

To something more like

boolean test = a>b;
digitalWrite(Pinnumber, test);

I don’t see any conversion function listed in the reference to do that, and doing it the long way just looks ugly to me.

A second problem I have is I’m creating a library that uses a 2 dimensional array, and you can’t do that unless you define the size of all but the first dimension… I really don’t want to hard code a limit in the library, is there any sort of workaround?

Rx7man: boolean test = a>b; digitalWrite(Pinnumber, test);

That's legal.

Rx7man: A second problem I have is I'm creating a library that uses a 2 dimensional array, and you can't do that unless you define the size of all but the first dimension... I really don't want to hard code a limit in the library, is there any sort of workaround?

Nope. That's a rule in c++.

Nope. That's a rule in c++.

You can define all of the dimensions. What you can't do is define a 2D array and expect it to grow automagically.

There's the ternary operator - does no favors for readability though:

digitalWrite(pin,test?HIGH:LOW);

you can even do

digitalWrite(pin, a > b);

as true == HIGH and false == LOW (by definition )

not very maintainable but ...

OK, I guess my error messages stem from something else, thanks.. I'll look into it further and figure that part out.

About the arrays

I'd like to define that there is a 2 dimensional array, but not allocate memory for it until the library's constructor, at which point the user can define the bounds for both dimensions... In VB, that I'm used to, it would be

Dim Array(,) as integer . . . Redim Array(3,7)

Rx7man:
Hello, I’m pretty new to any C style language, and Arduinos as well…

I’m wondering if there’s a neater way of doing this

if <true> {

digitalWrite(pinNumber, HIGH);
}
else{
digitalWrite(pinNumber, LOW);
}

I reckon it is much better to write code that is easy to understand - which this is. I suspect the output from the compiler will be much the same however it is written.

Of course if your code is really

if (myVal == true) {
    digitalWrite(pinNumber, HIGH);
}
else{
    digitalWrite(pinNumber, LOW);
}

You could simplify it to

digitalWrite(pinNumber, myVal);

without any loss of readability

…R

While Robin2 has provided a solution that works just fine, this usage is not supported by the reference documentation at http://www.arduino.cc/en/Reference/DigitalWrite

This documentation forces the usage of the opaque values HIGH and LOW, and does not say anything about using true and false.

The documentation should be updated but probably never will.

vaj4088, That is precisely why I asked the question, the documentation doesn’t mention being able to use boolean values, or any method of conversion between HIGH, LOW and TRUE, FALSE.

digitalWrite only tests for the value != 0. So, ANY uint8_t value will work, and will set the output LOW if that value is zero, or HIGH otherwise. digitalWrite(13, 255) will work just as well as digitalWrite(13, HIGH); How could a digital write do otherwise?

Regards, Ray L.

The digitalWrite() API defines the function as:
digitalWrite(pin, value) where value is either HIGH or LOW.
http://www.arduino.cc/en/Reference/DigitalWrite

While HIGH is currently defined as 1 and LOW is currently defined as 0, to take advantage of this as well as the internal coding implementation knowledge by passing in a true/false or 0/non-zero instead of using HIGH or LOW as the API defines, is abusing the API and is not good programming practice.

APIs should be used as defined/documented.

But I’m sure you guys that recommend doing this already knew that… :wink:

— bill

bperrybap: The digitalWrite() API defines the function as: digitalWrite(pin, value) where value is either HIGH or LOW. http://www.arduino.cc/en/Reference/DigitalWrite

While HIGH is currently defined as 1 and LOW is currently defined as 0, to take advantage of this as well as the internal coding implementation knowledge by passing in a true/false or 0/non-zero instead of using HIGH or LOW as the API defines, is abusing the API and is not good programming practice.

APIs should be used as defined/documented.

But I'm sure you guys that recommend doing this already knew that.... ;)

--- bill

Though it is a bit dopey that the value argument is type uint8_t, when there is no logical reason for it to be anything other than a boolean....

Regards, Ray L.

RayLivingston:
digitalWrite only tests for the value != 0. So, ANY uint8_t value will work, and will set the output LOW if that value is zero, or HIGH otherwise. digitalWrite(13, 255) will work just as well as digitalWrite(13, HIGH); How could a digital write do otherwise?

Regards,
Ray L.

OK here is an example:

The digitalwrite() API and parameters could have been defined such that LOW was zero and gives a steady low signal and HIGH was 255 giving a steady high signal and any value between LOW and HIGH would give a pwm value.
In fact, the API could be changed to work this way right now and for all the coders that properly followed the API and used LOW for a pin that should be low all the time and HIGH for pin that should high all the time, their code would continue to work.
Those that abused the API would have their code stop working properly because a 1 would be a very low duty cycle rather than a steady high signal and other “random” non zero values would result in various pwm signals.

And if you don’t like the LOW, pwm value, HIGH scenario consider a case where there is a core that implements digitalWrite() but the person who coded it checks for value != HIGH vs LOW in the code. In that implementation any value other than HIGH outputs a low signal.
So again, using a value other than LOW and HIGH can get you in trouble.

These are examples of the kinds of things that can happen when an API is abused and then the underlying implementation is changed to add new functionality or is implemented differently in different version of the code.
Those that followed the API have no issues, and those that abused the api get burned.

Best coding practices dictates that s/w should use an API as defined rather than try to take advantage of internal implementation details that are not documented and subject to change.

— bill

RayLivingston: Though it is a bit dopey that the value argument is type uint8_t, when there is no logical reason for it to be anything other than a boolean....

Regards, Ray L.

"logically" may be not, but there is a reason to use uint8_t vs boolean.

a boolean is an int and so using an actual boolean on an 8 bit AVR is slower than a uint8_t

Related to this, what is disappointing is that somebody recently got the brilliant idea to change the arduino "bool" type to be a boolean rather than being a uint8_t starting in arduino 1.6.0

The net result of that is that while you get slightly better type checking, the code will be now be slightly larger and slower since the processor has to check both bytes vs just one.

The better choice would be to make HIGH and LOW their own dedicated type and then use that type for the digitalWrite()/digitalRead() value parameter. That way there would be no way to abuse the API and user's would be forced to use HIGH or LOW.

The type could then be set to use the most efficient size/type for the given processor architecture.

--- bill

That 1.6 IDE seems to be trouble. Due support is not installed by default and it complains saying that boards with arduino.org on them aren't official Arduino boards. Then it installs stuff (in Windows) in a AppData location that very few people know about. Not to mention that it forcibly uninstalled my 1.5.8 so I can't go back to that easily.

I did not know that about booleans: they really always use the same storage space as an INT? Wow.

bperrybap: Best coding practices dictates that s/w should use an API as defined rather than try to take advantage of internal implementation details that are not documented and subject to change.

Unfortunately, even the reference page for digitalWrite doesn't really follow that suggestion.

http://www.arduino.cc/en/Reference/DigitalWrite

void digitalWrite(uint8_t, uint8_t);

Example code?

int ledPin = 13;                 // LED connected to digital pin 13
...
  digitalWrite(ledPin, HIGH);   // sets the LED on

Really, ledPin should be uint8_t (or byte) type.


And digitalRead?

int digitalRead(uint8_t);

That returns an int, but the reference defines it as returning LOW (0) or HIGH (1) which are not at either end of the scale for values of an int (-32768 to +32767). So the whole thing looks sloppy. One wonders, for example, what a negative return value could possibly mean?


Plus, from the above prototypes, digitalWrite writes an uint8_t (LOW or HIGH) but a digitalRead returns an int (LOW or HIGH). It just isn't consistent.

Having a 2-byte boolean type is just plain stupid.

I don't really "get" why there is a type boolean and a type bool. Why ? I use boolean for Java and bool for C.

I agree in principle with berrybap's view that "you should follow the api". It's somewhat unfortunate that the arduino API is so poorly specified.

But on the issue of a conditional test being false if zero, and true for everything else, I think you have to live with that, that horse bolted in about 1973 with C/C++ and it is too late to shut the stable door now. In fact I discourage our students from writing things like

if ( something == true ) ....

because it can lead to problems where something is non-zero but not the same as "true", which might be 1, or 0xFF, or whatever a #define buried somewhere says it is.

I discourage our students from writing things like

if ( something == true ) ....

What would be your preferred way to write this ?

where something is non-zero but not the same as "true", which might be 1, or 0xFF, or whatever a #define buried somewhere says it is.

If this happens then something could be any value so what do you test for ?

michinyon: In fact I discourage our students from writing things like

if ( something == true ) ....

Well, of course. If you are going to write that, you may as well write:

if ((something == true) == true) ...

Which leads us to:

if (((something == true) == true) == true) ...

And so on.

UKHeliBob:
What would be your preferred way to write this ?
If this happens then something could be any value so what do you test for ?

In C, non-zero in a condition is considered true. So comparing to true is not only redundant, but incorrect.

If you are going to compare to true, you can get this sort of situation:

if (something == true)
  <whatever>
else if (something == false)
  <whatever>
else
  <some other action>