changings specific bits in a byte var

stocky

Senior Member
Sorry if this is a silly question!

I have an app writing to a PCF8574 i/o expander running 8 leds used to indicate the status of various things going on in my 28x1.

I have the i2c running fine and have another PCF8574 on the same bus running 8 inputs (just having fun getting the INT function to work ATM!)

I have a byte var (SYMBOL LEDS = b8) as the byte indication the status of the leds - what I'm trying to do is update the leds one at a time as the program runs its course.

Would the correct method of say updating the 5th leds value (bit6) be:

LEDS = LEDS + 1 & %00100000 (or similar - syntax might be wrong)

To my thinking that adds 1 to the value of LEDS, but masks it to the 6th bit only? Is that correct or am i WAYYYY off track here?

Cheers
 

hippy

Ex-Staff (retired)
The best way is to use the & (And), | (Or) and ^ (Xor) operators ...

LEDS = LEDS | %00100000 ' Set bit 5
LEDS = LEDS & %110111111 ' Clear bit 5 ( ie, don't clear any but Bit 5 )
LEDS = LEDS ^ %00100000 ' Toggle bit 5

Remember bit numbering start at zero on the right, the first LED is likely on bit 0, so the fifth LED if sequential would be bit 4.

An alternative is to move your byte into variable 'b0' then use the bitX variables ...

b0 = LEDS : bit5 = 1 : LEDS = b0 ' Set bit 5

It's not code efficient but in some cases it can be very useful. Of course, if you "Symbol LEDS=b0", you can just use "bit5=1".
 

stocky

Senior Member
Cheers Hippy

I am counting my leds in reverse - so i'm workign MSB - LSB anyway :)

I'll have a play with the examples you show tonite and see what works for me :)

thanks for speedy reply!
 

westaust55

Moderator
If your are trying to count using the LED’s to display a value from 0 to 255 corresponding to progress or so other conditions then just add one each step/stage of the program.

If you are only looking to indicate 8 stages or points in the program as the action progresses from start to end then just shift the bit along may be an option.

So LEDS = 1 at the start (right to left progress across LEDs) or LEDS = 128 (for left to right )

Then for each subsequent stage use:
LEDS = LEDS * 2 (right to left) or LEDS = LEDS / 2 (for left to right)
or since you have the 28X1
you could also use LEDS = LEDS << 1 (R to L) or LEDS = LEDS >> 1 (L to R)

BUT, if you are trying to track when you are at various subroutines, etc, so position withint the program is jumping back and forth or want more than 8 combinations, then you will need to set and clear individual bits using the method that Hippy has indicated.
 

stocky

Senior Member
Cheers Westie - what I am doing is more suited to Hippys method I think.
I have routines to do the "binary" thing and and general "lamp check" routines functioning already.

The 8 leds indicate program steps, fault conditions, switch "modes" etc - so the bitwise method is how i need to go. The environment is a big "rugged" and variable widely in temps - so while i thought about an LCD i decided LEDS more rugged!

Thanks for your input :)
 

moxhamj

New Member
I'll second hippys suggestion of using the 'bit' commands. They only work on byte b0 b1 but it is usually easy to configure code to use those bytes. Then you can set individual bits.
 

stocky

Senior Member
i assume if i use the bit command i can do the reverse as well and query a bit?

if bit 5 = 1 then.........??
 

stocky

Senior Member
Thanks guys - works a treat!

And because I'm using a 28x1 i have bits 0-31 to play with! :)

I am now using:
bits 0-7 for LED status
Bits 8-15 for input status
Bits 16-23 for status flags
and I have 8 spare :)

Ta for pointing in right direction - have never used "bits" before

Stocky
 

stocky

Senior Member
Hippys suggested method has worked quite nicely for my app - ta hippy!

Sorry if this seems like thinking out loud.....

My query now is in relation to the inability to do maths IN an if-then statement.

Say I have two "bits" RUN_FLAG & SPEED_IN and I need to test for RUN_FLAG = 1 and SPEED_IN = 0 or 1 and act on that.

I guess I could just assign a var to an equation:

bX = RUN_FLAG + SPEED_IN
if bX = 1 then do_something
if bX = 2 then do_something else

But do to the number of these tests i need to run in a routine called from a gosub i might have to use a SINGLE var and clear it back to ZERO between each lot of tests...28x1 is fast enough to not have noticeable lag i think.

If this a fair way to do this - or has someone a better/neater/smaller/faster idea?

Stocky
 
Last edited:

hippy

Ex-Staff (retired)
If these are bits in bit variables you can do things like, "If bit0=1 And bit1=0 Then", or in this case, "If RUN_FLAG=1 And SPEED_IN=1 Then".

You're on sticky ground with mixed And and Or, "If bit0=1 And Bit1=1 Or bit2=1 Then", but you can usually split them into separate IF-THEN commands.

I'd also recommend using nested IF-THEN-ENDIF rather than 'IF-THEN label' as it will often keep a design much clearer and understandable. Code common to multiple parts can usually be put into subroutines. Not usually a problem except for the smaller PICAXE's.
 

stocky

Senior Member
ahh - PERFECT! Thanks again!

I'll use seperate if-then statements :)

FYI - I'm working on a general purpose engine controller for pump or genset applications

lots of inputs & outputs & status flags to "watch" and "test" - the "bits" are working very well for me in this regard

I have two i2c i/o expanders running (one for in & one for out) - I did it this way to "steal" the INT pin to give me "interrupt" on ANY change of state on ANY pin on the "inputs" expander.

I'm testing for certain sequences on startup to indicate success, and certain status changes while "running" to shutdown and record fault codes for later analysis

Current code is only about 600 bytes with all the basics covered - later revisions will have RS485 or RF comms - hence the use of the 28x1 and leaving spare "native" io pins

Might still add a 3rd io expander yet to read in "settings" from a more DIP switches or BCD switches
 
Last edited:
Top