Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

unhappy with code I wrote. It works BUT??

Status
Not open for further replies.
I searched the help in swordfish under alias , arrays,and variables and still can't figure out how to use a 16 bit variable.
Doing back to what I can accomplish and works. Might not be pretty but it should work. My first posted code works even after I removed the suggested lines of code.
At this point am trying to use a FOR NEXT loop to scan the switches but using the leds to indicate that the FOR NEXT loop is actually working BUT how to dimension the arrays (led(x)
 
tmp_11648-SmartSelectImage_2017-01-26-06-35-47-1102591899.png


If you dimension a variable as a WORD, it's 16 bits.

In my above post the variable was SWITCHES.

Dim SWITCHES As Word

makes SWITCHES a 16 bit variable.
 
Last edited:
What to do with a 16 bit variable?? so I cobbled this together and it works as planned BUT still wanting to insert a cathode switch (see notes) as my PWM designation. This is just two of a total of 10 IF THEN statements. Plan on doing a little editing as per suggestions.
NOTE just got off phone w /Mouser about lighted tactile switches that are supposed to come w/ caps part# TL1240R1JCLR. Somebody had wrong Mouser # 612-TL-1240R. They are sending either 10 more switches w/ caps or just the caps. Nice company to deal with IMO

// My objective is to monitor 10 switches using an 18F4520 pic. This is just
// a testing routine to determine if the sequence of events will work
// leds are OFF until the designated switch is depressed then stay ON until the designated switch is depressed again.
// can't help it but I feel this code could be better?? tooo many if thens??
//my plan is to designate each switch and led (swt1 and led1)
DEVICE = 18F4520
CLOCK = 8
INCLUDE"InternalOscillator.bas"
INCLUDE "SetDigitalIO.bas"
CONFIG MCLRE = OFF
// alias to port pin...
DIM PWM AS porta.3
DIM x AS BYTE
DIM y AS BYTE
DIM led0 AS PORTc.0
DIM LED1 AS portC.1
DIM LED2 AS PORTc.2
DIM led3 AS portC.3
DIM led4 AS PORTc.4
DIM LED5 AS portC.5
DIM LED6 AS PORTc.7
DIM led7 AS portd.3
DIM led8 AS PORTD.4
DIM LED9 AS portD.5

DIM swt0 AS portB.0
DIM swt1 AS portB.1
DIM swt2 AS portB.2
DIM swt3 AS portB.3
DIM swt4 AS portB.4
DIM swt5 AS portB.5
DIM swt6 AS portD.0
DIM swt7 AS portD.1
DIM swt8 AS portD.2
DIM swt9 AS portD.6

// sub routines

OUTPUT (led0)
OUTPUT (LED1)
OUTPUT (LED2)
OUTPUT (led3)
OUTPUT (led4)
OUTPUT (LED5)
OUTPUT (LED6)
OUTPUT (led7)
OUTPUT (led8)
OUTPUT (LED9)

OUTPUT (swt0)
OUTPUT (swt1)
OUTPUT (swt2)
OUTPUT (swt3)
OUTPUT (swt4)
OUTPUT (swt5)
OUTPUT (swt6)
OUTPUT (swt7)
OUTPUT (swt8)
OUTPUT (swt9)
OUTPUT (PWM)



led0 =0
LED1 =0
LED2 =0
led3 =0
led4 =0
LED5 =0
LED6 =0
led7 =0
led8 =0
LED9 =0

swt0 = 1
swt1 = 1
swt2 = 1
swt3 = 1
swt4 = 1
swt5 = 1
swt6 = 1
swt7 = 1
swt8 = 1
swt9 = 1
PWM = 1
x = 0
// main program...
WHILE true
//#0
IF swt0 = 0 AND LED3 = 0 // button press
THEN
LED3 = 1
DELAYMS(500) // switch debounce
END IF
IF swt0 = 0 AND LED3 = 1 'second time button press
THEN
LED3= 0
DELAYMS(500)
LED3 = 0
END IF

'xxxx #1
IF swt1 = 0 AND LED2 = 0 // button press
THEN
LED2 = 1
DELAYMS(500) // switch debounce
END IF
IF swt1 = 0 AND LED2 = 1 'second time button press
THEN
LED2= 0
DELAYMS(500) // turn OFF led after second button press
LED2 = 0
END IF
// i TRIED INSERTING THE CATHODE TO GROUND SWITCH HERE AFTER EACH SWT CHECK W/ 200MS DELAY BUT IT TURNS OFF THE LED ANDD BLINKS DIM.
'xxxx #2
 
Get all your switches into one 16 bit variable (current).
Keep a copy of the previous state of the switches (previous).
If you xor the two together it has a 1 for each switch that has changed state. (Current xor previous)
If you AND the result of last xor with current key variable it will have a 1 for each new key press. (current xor previous) and current
If you xor this with a variable representing the LEDs you will have the new state for the LEDs.
Do this every 20mS for perfectly debounced switches.
Mike.

it sounds easy enough but not familiar with XOR or how to save and deal with a 16 bit variable.
need to do some research

A "16 bit variable" is a word.

Dim Switches As Word

Search Swordfish Help for variables and alias.

Say your switches are on all of Port B and bits 0 - 3 of Port C. Something like this gets all of your bits into the same place. Read the documentation - it's 5am and I'm doing this from memory so the syntax may not be exactly right.

Switches.lowbyte = Port B

Switches.highbyte = (PortC AND %00001111)

"AND %00001111" masks out the upper 4 bits and gives you the lower 4 bits.

Switches.highbyte = PortC.lowernibble

might work but I don't recall. Check the Swordfish documentation on alias.

I searched the help in swordfish under alias , arrays,and variables and still can't figure out how to use a 16 bit variable.

View attachment 103814

If you dimension a variable as a WORD, it's 16 bits.

In my above post the variable was SWITCHES.

Dim SWITCHES As Word

makes SWITCHES a 16 bit variable.

What to do with a 16 bit variable??


You're probably not familiar with how forums work. You ask a question. People give you answers. For most people, these answers build on one another. Information is provided; information is expanded upon as needed. Forum posts build on the posts that have come before.

Pommie suggested a very easy, effective approach, gathering all the port bits into one variable, and comparing what it is now to what it was using XOR. A few lines of code, and you can detect every change in switch state (state is whether they are pushed or not).

You didn't know that a WORD contains 16 bits - i.e., a WORD is a 16 bit variable. I explained that and explained how to gather all the bits into a single variable dimensioned as a WORD and where to find the fancy words I had used in the Swordfish documentation. When your research still didn't help, I posted a table from the Swordfish documentation explaining each variable type. For example, a BYTE contains 8 bits. A WORD contains 16 bits. An INTEGER also contains 16 bits, but can represent positive or negative numbers.

And finally, I am pointing out to you the purpose of a 16 bit variable, since you seem to have forgotten.

There, now you are up to date. Feel free to continue making random nonsensical changes and posting long blocks of code that nobody reads.
 
Last edited:
I idea that Pommie posted sounds good but IMO beyond my present knowledge of programming a pic.
 
It's unfortunate that you couldn't be troubled to take a few minutes to learn something new, because Pommie's technique is really simple and cuts out a lot of code.

Here's an example from software I'm working on right now.

DisplayData comes from reading PortB; the 8 bits represent 8 alarm conditions. Some of those bits are normally high and an alarm condition is indicated by a low bit. Others are normally low, and an alarm condition is represented by a high bit. To account for the different conditions of the 8 monitored signals, the variable NormalMask represents the normal state of each bit.

When a bit from DisplayData doesn't match the bit in NormalMask, that bit should be set to 1 to turn the associated LED on. The comparison is easing using XOR; XOR means Exclusive Or...or in simple terms, one or the other but not both.

The code is simple:

DisplayData = DisplayData Xor NormalMask

if the DisplayData bit matches the NormalMask bit, the output is zero and the associated LED is off. If the 2 bits don't match, the output is 1 and the LED is on. Eight LEDs set in one line.

Let's say NormalMask = %00001111. The 4 high bits are normally low, and the low 4 bits are normally high.

And lets say DisplayData = %10001111. Bit 7 (on the left) is high, an alarm condition.

DisplayData Xor NormalMask = %1000000.

If my LEDs are on PortC, saying

PortC = DisplayData turns on one of the LEDs and the other 7 off.

Here's a truth table for the Xor function.

Code:
Input 1  |  Input 2  |  Output
    0        |     0         |     0
    1        |     0         |     1
    1        |     0         |     1
    1        |     1         |     0

Xor makes this comparison for each bit in a pair of variables. If the 2 variables being compared are dimensioned as bytes, the comparison will be for 8 bits. If the two variables are dimensioned as words, 16 bits will be compared.


For your case, say your switches are on PortB and your LEDs are on PortC.

Code:
SwitchesWere = PortB
While 1 = 1
     Switches = PortB
     PortC = Switches Xor SwitchesWere
     SwitchesWere = Switches
     DelayMS(20)
Wend

I explained previously how to get your 10 bits into word variables. This turns the LEDs on when the button is pressed and off when it's released. A little additional logic is required to toggle the LEDs....about this many more lines.




[/code]
 
Last edited:
only 1 problem is that the bits are not in much order ... so it wont be that simple,
where is portC6?... is it available to use....
It could make code life easier if you can change your LED ports so that there is more alignment between led and sw:
c0,c1,c2,c3,c4,c5,c6,c7,d1,d2,

and switches pins to:
b0,b1,b2,b3,b4,b5,b6,b7,d3,d4


or maybe what might help is if we can define leds and sw to a bit ARRAY,.... If its even possible in swordfish,idk,
ie:
DIM LED[1] AS portC.1
DIM LED[2] AS portD.3
 
.....or maybe what might help is if we can define leds and sw to a bit ARRAY,.... If its even possible in swordfish,idk,
ie:
DIM LED[1] AS portC.1
DIM LED[2] AS portD.3.....


I don't believe that's possible in Swordfish Basic.

This is definitely the place where circuit arrangement is important, and something I need to consider more. Put the switches at least on the same port.
 
I think that was the attempt in post 39 led(1)= portc.1
it should be more like this:
DIM led AS WORD
// google bitwise operators
led = 0;
led &= portc.1 <-- first bit
led &= portc.2<<1 <-- second bit
led &= portc.3 <<2 <-- third bit

unless we are able to define each bit as such that wont work... if not we may need calls to refresh led values aswell....

I think alot MR's confusion lies in the differences between variable "data types", arrays of "datatypes", and bitwise operations in a single variable of a datatype,
as well as a confusion between definition of pins and declaration of variables .... i notice swordfish uses DIM for both

;.... also what is the output function in #32, why are we outputting switches>?
 
I tried putting all in an orderly fashion but portB6 and B7 can't be used with a pull-up resistor attached. B6 & B7 are PGD and PGC. connecting a pull-up connected to Vcc comes up with a Vcc error in pick 2.
On the proto type I found I have an 18F4520 with portC.1 bad and another same with another bad port pin on C7?. Had to change wiring connections. On my rev 3 that I have pcboards ordered I am only using 8 switches and 8 leds as well as an 18LF2420. I have the connections for switches on portB0-B5 & A0 & A1
leds on port port C0 - C7
I tried putting all the switches on portC but it seemed to look better with switches on port A0 and A1. Am using all smd and avoiding traces running between resistor pads.
If I could have all the leds AND switches all in a row (switches all on portC and all he leds on portB then just use (portB.bits(x) to scan all of port B and portC in one fell swoop. I think 4 IF THEN lines of code within a FOR NEXT loop
 
What you can connect to B6 and B7 is limited when you're using ICSP, but 10k pullup resistors work fine. I do it all the time.
 
I had the 10K resistor connected to Vcc and portB6. The switch connected directly to B6. Tried programming and couldn't as I kept getting a voltage error.
Clipped the resistor off and moved the switch connection/10K resistor to another port. All worked fine.
After the discussion yesterday about all the ports in a row I realized a mistake concerning my schematic and pcboard layout,
I originally drew up the schematic using 10 switch/ led combinations. I reduced to 8 and failed to redo port assignments thus eliminating pcboard woes.
 
Matrix software isn't difficult at all. Below, you'll see just how few lines it takes to do what you want.
One of the benefits of microcontrollers is that you can use your pins for more than 1 or 2 different functions.
Here's an example in PicBasic of how to read a 2x5 matrix:

main:
porta = %00000001 'set porta pin 0 high
if portb != 0 then gosub check1 'if portb has a high pin, go see which one it is. Otherwise,
porta = %00000010 'set porta pin 1 high
if portb != 0 then gosub check2 'if portb has a high pin, go see which one it is
goto main

check1:
LED = (ncd PORTb & %00011111) ' Masks off all but the first 5 portB pins, then ncd turns it into an integer between 1 and 5
gosub lightLED ' Take that number and go light up your LED, use a lookup table, or whatever...
RETURN
check2:
LED = (ncd PORTb & %00011111)+5 ' Masks off all but the first 5 portB pins, then turns it into an integer between 6 and 10
gosub lightLED
RETURN
LightLED:
'turn on (or off by setting or resetting a flag, for example) your LED whichever way you choose.
 
sry MR, was just a suggestion for port alignment... actually as a novice, i stick with this rule to eliminate similar issues..
1. Do not use RB6/RB7 so they are dedicated to ICSP.

I found the SF user guide and some things that may help:
https://www.sfcompiler.co.uk/downloads/SFManual.pdf

consider this:

Code:
public dim SwitchState(10) as bit
public dim LastSwitchState(10) as bit

public dim Ledstate(10) as bit
public dim ctr as byte
 

sub setLED(bit status, byte pos)
select pos
case 1 PORTC.1 = status
case 2 PORTC.2 = status
case 3 PORTC.3 = status
case 4 PORTC.4 = status
endselect
end sub

function readSwitches(byte pos) as bit
select pos
case 1 return PORTB.1
case 2 return  PORTB.2
case 3 return PORTB.3
case 4 return PORTB.4
endselect
end function


void main        {       /// I will let you remove this line but this is where main program should start

while true
for ctr = 0 to 10
SwitchState(ctr) = readSwitches(ctr)

IF SwitchState(ctr)=0  AND SwitchStateLast(ctr) = 1 THEN

IF Ledstate(ctr)=0 THEN
Ledstate(ctr)=1
else
Ledstate(ctr)=0
END IF

DelayMS(20)
END IF

SwitchStateLast(ctr)=SwitchState(ctr)
setLED(Ledstate(ctr), ctr)

next ctr
wend

}     // other bracket for void main
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top