PDA

View Full Version : Control a Radio PLL with a PIC



RayL113
- 11th June 2011, 00:50
I am very new to the PIC world and to PBP. So if I ask what seems like a dumb question, please bare with me.
I want to control an old Knight Kit 2 meter radio.
It currently uses a thumbwheel to program the PLL in Binary.
The count starts at 000000000. And ends at 011111111.
I want to use an Encoder with 2 outputs. CW/CCW. Using a +5 volt reference.
So each pulse is a logical 1.
It will either increment the count by 1 or decrement the count by 1 depending on which way the encoder is turning.
CCW will equal Down pulses on RA2, CW = Up on RA3.
The PLL program pins require +5 volt logical 1 for selection.
I also want to display the count from 0 to 255 in decimal on a 3 digit 7 segment LED display.
PIC is an 18F6680.

I tried doing this as asm but didn't get anywhere.
It seemed like it should be straight forward, but I quickly discovered it wasn't.

I thought about using Button to monitor the two input lines but read in the manual that this would not be good for what I want to do.

I searched the forum looking for something similar but couldn't find anything related.
Any suggestions or thoughts on how I should approach this in PBP?
All comments welcome.
Thanks

cncmachineguy
- 11th June 2011, 02:05
Sounds like FUN! First let me say, I think if you search on encoder, you may have better results. I am pretty sure there is at least an article.
Now having said that, I have some questions for you. Encoders usually have an A and a B channel. are these what you are calling the CW and CCW outputs? If so is this an encoder with extra drive board or something?

Are you planning to didicate 8 lines to the PLL, 10 lines to the display and 2 lines to encoder? Or do you have a different hardware plan?

This will be pretty straight forward, but we need to know what background you do or do not have so far for this.

Are you set fast on the uP? if you are just starting out with PIC's you may want to consider a 16F device. Just my opinion.

Archangel
- 11th June 2011, 03:31
That's funny. I just ordered 2 pic18f4431 s on Thursday for this specific purpose. I found even using asm interrupts the 16f690 too slow to track the encoder without losing steps, (either that or it was switch bounce). So I figure to use a PIC with QEI Hardware inputs and a 40mhz clock. Failing that I will try using flip flops to buffer the inputs. In any event there is plenty to learn.
Now off to Costco for a box of Corn Nuts, and 3 pounds of coffee . . .
Edit:


I also want to display the count from 0 to 255 in decimal on a 3 digit 7 segment LED display.
PIC is an 18F6680.

Or you can use a lookup table and display channels or frequency.

cncmachineguy
- 11th June 2011, 05:05
Joe, How fast are you spinning the encoder? How many CPR? I have been using 500 line (2000 CPR) encoder for a gate position applacation for about 6-7 years now. No bounce because they are optical. never lose any pulses, but they are going pretty slow. (30RPM) 1000 cps. I am doing this with 16F676, no interrupts just checking the A-B states in my main. It is a fast main loop but never the less. Oh and running on 4Mhz internal OSC

Archangel
- 11th June 2011, 07:09
Joe, How fast are you spinning the encoder? How many CPR? I have been using 500 line (2000 CPR) encoder for a gate position applacation for about 6-7 years now. No bounce because they are optical. never lose any pulses, but they are going pretty slow. (30RPM) 1000 cps. I am doing this with 16F676, no interrupts just checking the A-B states in my main. It is a fast main loop but never the less. Oh and running on 4Mhz internal OSC
Hi, I am using the "El Cheapo" mechanical encoders similar to a rotory switch, just 3 terminals A com B tried both kinds gray scale and quatdradture. I think it is losing counts during the serout routine, it should not but it does, again it could be noisy encoder too, I will know better when I get those PICs next week. I have some optical encoders here, but they have a bizillion steps per rev. These switch type have 24.
Here is the code:


@ __config _HS_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _FCMEN_OFF & _BOR_OFF

'************************ DEFINES HERE *************************************
DEFINE OSC 20 ' set to 20mhz
INCLUDE "MODEDEFS.BAS"
clear ' clear out variables
DEFINE DEBUG_REG PORTC
DEFINE DEBUG_BIT 6
DEFINE DEBUG_BAUD 19200
DEFINE DEBUG_MODE 0

'********************** PIC16F690 setup ************************************
ADCON0 = 0
ADCON1 = 0
ANSEL = 0
ANSELH = 0
CM1CON0 = 0
CM2CON0 = 0

TrisA = %00000000
TrisB = %11000000
TrisC = %00000000

'*********************** ASSEMBLY INTERUPT VARIABLES ***********************
wsave var byte $20 system
wsave1 var byte $a0 system ' Necessary for devices with RAM in bank1
wsave2 var byte $120 system ' Necessary for devices with RAM in bank2
ssave var byte bank0 system
psave var byte bank0 system

'************************************************* **************************
enc_old VAR BYTE
enc_new VAR BYTE
enc_tmp var byte
enc_counter VAR BYTE
enc_counter_old VAR BYTE
enc_scaler var BYTE
Display Var Byte

INTCON = %10001000 ' Enable PortB Change Interupts
IOCB = %11000000
pause 5500 ' wait for LCD to start

goto start 'skip over interupt handler
'*********************** ASSEMBLY INTERUPT HANDLER *************************

define INTHAND myint
Asm

myint




;====== BEGINNING OF THE ROTARY ENCODER CODE ========
;The Rotary Encoder is connected to PORTB
;The A signal of the encoder connected to the PIN portB.7
;The B signal of the encoder connected to the PIN portB.6
;
;The 4 variables used are declared in the PicBasic code.
;
; enc_new VAR BYTE
; enc_old VAR BYTE
; enc_tmp VAR BYTE
; enc_counter VAR WORD
;
;================================================

;Read latest input from PORTB & put the value in enc_new.
movf PORTB,W
movwf _enc_new

;Strip off all but the 2 MSBs in enc_new.
movlw 0xc0 ;Create bit mask (bits 7 & 6). b'11000000' ?
andwf _enc_new,F ;Zero bits 5 thru 0.

;check to see if encoder has moved
movf _enc_old,W ;move enc_old to W
movwf _enc_tmp ;put W to enc_tmp
movf _enc_new,W ;move enc_new to W for XOR
xorwf _enc_tmp,F ;XOR enc_tmp to detect encoder movement
btfsc _enc_tmp,7 ;if bit is clear, encoder moved.
goto Continue ;no movement exit isr

;Determine the direction of the Rotary encoder.
rlf _enc_old,F ;left shift it into _enc_old to align bit 6 of
;_enc_old with bit 7 of enc_new.

movf _enc_new,W ;Move the contents of enc_new to W in order to XOR.
xorwf _enc_old,F ;XOR previous inputs (in _enc_old) with latest
;inputs (in W) to determine CW or CCW.

btfsc _enc_old,7 ;Test bit 7 of result (in _enc_old). Skip next line
;if it is 0 (direction is CCW).
goto Up ;Bit is 1 (direction is CW). Go around Down
;and increment counter.

Down
;Decrements enc_counter because the rotary encoder moved CCW.
;Decrements enc_counter (16 bit value), sets Z on exit.

decf _enc_counter,F ; Decrement low byte
incfsz _enc_counter,W ; Check for underflow
incf _enc_counter+1,F ; Update
decf _enc_counter+1,F ; Fixup
movf _enc_counter,W
iorwf _enc_counter+1,W ; Set Z bit


;Add here code for the CCW LED if needed.
;bsf _led ;turn on led

goto Continue ;Branch around UP.

Up
;Increments enc_counter because the rotary encoder moved CW.
;Increments enc_counter (16 bit value), sets Z on exit.

incfsz _enc_counter,W ; Add one to low byte
decf _enc_counter+1,F ; No carry (negates next step)
incf _enc_counter+1,F ; Add one to high byte
movwf _enc_counter ; Store updated low byte back.
iorwf _enc_counter+1,W ; Set Z flag


;Add here code for the CW LED if needed.
;bsf _led2 ; turn on led

Continue
; Assign the latest encoder inputs (in enc_new) to _enc_old.
movf _enc_new,W
movwf _enc_old

; Restore saved registers
movf psave, W
movwf PCLATH
swapf ssave, W
movwf STATUS
swapf wsave, F
swapf wsave, W
bcf INTCON, RABIF ; Clear the Interupt Flag
RETFIE ; Return from interrupt
endasm

'************************************************* **************************
'************************* PROGRAM STARTS HERE *****************************
'************************************************* **************************

START: ' Main Program starts here




enc_counter = 0 ' set default encoder value
enc_counter_old = 0
' DEBUG 254,2, "ENCODER " ' change display
' DEBUG 254,192,#Display," "
' DEBUG 254,148," " ' clear display
' DEBUG 254,212," "

MAIN: 'see if value has changed
if enc_counter <> enc_counter_old then enc_counter_old = enc_counter
Display = (enc_counter/2)




DEBUG 254,2,"ENCODER " ' change display
DEBUG 254,192,#Display," "
DEBUG 254,148," " ' clear display
DEBUG 254,212," " ' display enc_counter value
sound portC.7,[display,1]

goto MAIN
Got it here, more or less: http://www.picbasic.co.uk/forum/showthread.php?t=9700

It actually works a bit better using serout instead of debug, at least as far as the display goes, but is faster using debug, in terms of how fast the loop cycles.
I really have not invested that much time into it.

RayL113
- 11th June 2011, 08:20
Sounds like FUN! First let me say, I think if you search on encoder, you may have better results. I am pretty sure there is at least an article.
Now having said that, I have some questions for you. Encoders usually have an A and a B channel. are these what you are calling the CW and CCW outputs? If so is this an encoder with extra drive board or something?

Are you planning to didicate 8 lines to the PLL, 10 lines to the display and 2 lines to encoder? Or do you have a different hardware plan?

This will be pretty straight forward, but we need to know what background you do or do not have so far for this.

Are you set fast on the uP? if you are just starting out with PIC's you may want to consider a 16F device. Just my opinion.

Thanks for the reply. I'll try to answer as best I can.
The encoder acts like two momentary switches. It has 3 pins. Center is common and the two outside pins complete the switch. When turning in one direction only 1 pin has high pulses.
Not Gray code.
10 lines for the PLL and 11 for the display (decimal point)
My background is machine language only. No C or Visual Basic.
And yes. Set fast on the processor. Have already purchased 10 of these. Have a lot more projects I want to try.

RayL113
- 11th June 2011, 08:24
That's funny. I just ordered 2 pic18f4431 s on Thursday for this specific purpose. I found even using asm interrupts the 16f690 too slow to track the encoder without losing steps, (either that or it was switch bounce). So I figure to use a PIC with QEI Hardware inputs and a 40mhz clock. Failing that I will try using flip flops to buffer the inputs. In any event there is plenty to learn.
Now off to Costco for a box of Corn Nuts, and 3 pounds of coffee . . .
Edit:

Or you can use a lookup table and display channels or frequency.

Do you have an old Knight Kit radio as well?
Display channels or frequency? This sounds great. How would I do that?
My displays are only 3 digits.

Archangel
- 11th June 2011, 08:49
Do you have an old Knight Kit radio as well?
Display channels or frequency? This sounds great. How would I do that?
My displays are only 3 digits.

Nope no Knight kit, I was thinking of a retrofit for old 23 ch CB radios make them useful, other freqs, 10M . . . set a couple of vars
temp var byte
i var byte
lookup i[010,020,030 . . .500],temp this aliases your count to the numbers in the lookup table . . . You could set a freq switch with static displays like 142, 143, 144 . . . and follow with the displays driven by the lookup table displaying the fine freqs. Or change up to a word var and you have up to 65535 values you could step through, or use 2 encoders (old Henry 2m used 2 switches ganged) sorry about the code formats, crazy forum software glitch killed formatting for me, so I had to do it this way.

RayL113
- 11th June 2011, 14:41
Var, I take to mean variable. Remember I'm new to Pics and PBP. So a word var? Is this an extended table?

mackrackit
- 11th June 2011, 16:00
From the manual

4.3. Variables

Variables are where temporary data is stored in a PICBASIC PRO™ program. They are created using the VAR keyword. Variables may be bits, bytes or words. Space for each variable is automatically allocated in the microcontroller=s RAM by PBP. The format for creating a variable is as follows:

There are basically four sizes a VAR can be while using PicBasicPro 2.6x
BIT = number of BITs - 1
BYTE = number of BITs - 8
WORD = number of BITs -16
LONG = number of BITs - 32

Ioannis
- 11th June 2011, 21:20
For the Rotary Encoder have a look at this approach.

I wanted to do it also with interrupts, but I got interrupted many times!

http://www.picbasic.co.uk/forum/content.php?r=144-New-approach-to-Rotary-Encoder#new_comment

Ioannis

Archangel
- 12th June 2011, 01:05
Yes, var= variable
bit is one of the placeholders in the larger variable, example
say you want a variable to hold a value as a flag for an event, you could make a bit variable, called . . . FLAGBIT this way FLAGBIT VAR BIT
or you might need several flag bits and do it this way
FLAGBIT VAR BYTE which gives you an 8 bit byte full of FLAGBITS as follows
FLAGBIT.0 lowest bit in the byte
FLAGBIT.1 second bit in the byte
FLAGBIT.2 third " " " "
FLAGBIT.3 . . .
FLAGBIT.4 . . . all the way to FLAGBIT.7 , FLAGBIT.7 being the highest order bit in the byte variable
which is to say you can address every bit of your variable individually.
Byte = %00000000 will hold 0 to 255 in decimal
word = %00000000 00000000 will hold 0 to 65535 in decimal
LONG = %00000000 00000000 00000000 00000000 which is 4294967295 but I think (I am not sure of this) only allows 1/2 that much on each side of zero -2147483647 0 2147483647

Notice the way I have written the binary expression %00000000 this is the appropriate syntax for P Basic Pro, other compilers may use different "punctuation" and you will see "BIG ENDIAN" and LITTLE ENDIAN" usage and all that means is which end of the group of zeros is the least significant bit, the Left or the Right.

You will see different ways of displaying hex as well, in PBP we use $00 whereas in C you might see something like 0h00

mister_e
- 12th June 2011, 01:53
in PBP we use $00 whereas in C you might see something like 0h00
high likely 0x00 ;)

RayL113
- 12th June 2011, 05:03
For the Rotary Encoder have a look at this approach.

I wanted to do it also with interrupts, but I got interrupted many times!

http://www.picbasic.co.uk/forum/content.php?r=144-New-approach-to-Rotary-Encoder#new_comment

Ioannis

Now that's more my speed!
Simple but elegant. And all I would need to do is change the "if portb.1=0 then" to "if porta.2=1 then" , etc. right?

RayL113
- 12th June 2011, 05:09
Yes, var= variable
bit is one of the placeholders in the larger variable, example
say you want a variable to hold a value as a flag for an event, you could make a bit variable, called . . . FLAGBIT this way FLAGBIT VAR BIT
or you might need several flag bits and do it this way
FLAGBIT VAR BYTE which gives you an 8 bit byte full of FLAGBITS as follows
FLAGBIT.0 lowest bit in the byte
FLAGBIT.1 second bit in the byte
FLAGBIT.2 third " " " "
FLAGBIT.3 . . .
FLAGBIT.4 . . . all the way to FLAGBIT.7 , FLAGBIT.7 being the highest order bit in the byte variable
which is to say you can address every bit of your variable individually.
Byte = %00000000 will hold 0 to 255 in decimal
word = %00000000 00000000 will hold 0 to 65535 in decimal
LONG = %00000000 00000000 00000000 00000000 which is 4294967295 but I think (I am not sure of this) only allows 1/2 that much on each side of zero -2147483647 0 2147483647

Notice the way I have written the binary expression %00000000 this is the appropriate syntax for P Basic Pro, other compilers may use different "punctuation" and you will see "BIG ENDIAN" and LITTLE ENDIAN" usage and all that means is which end of the group of zeros is the least significant bit, the Left or the Right.

You will see different ways of displaying hex as well, in PBP we use $00 whereas in C you might see something like 0h00

Thanks that helps alot. Yes I had noticed the % in front of what looked like binary expressions but hadn't noticed the $ in front of hex expressions. Can you still use the "b and h" in PCB? In case I forget and use the asm expression?

mackrackit
- 12th June 2011, 06:42
Can you still use the "b and h" in PCB?
Nope.
From the manual.
4.8. Numeric Constants


PBP allows numeric constants to be defined in the three bases: decimal, binary and hexadecimal. Binary values are defined using the prefix '%' and hexadecimal values using the prefix '$'. Decimal values are the default and require no prefix.

100 ' Decimal value 100
%100 ' Binary value for decimal 4
$100 ' Hexadecimal value for decimal 256

RayL113
- 7th July 2011, 23:56
What if I want to use a cb channel switch instead of an encoder? The first four pins have a logical progression of 0000 to 1111. Couldn't I use this like a Gray code encoder? Count increase would equal up and count decrease would equal down. What do you think?

cncmachineguy
- 8th July 2011, 02:44
You can use that, you can use the thing you already have, its up to you. They both CAN work. With the CB switch you will only get 16 changes per full revolution. If this is enough then use it. It will prolly still have noisey output so de-bouncing will still be neccessary. Now if you can get this (http://usdigital.com/products/encoders/incremental/rotary/kit/e4p), I have used many, they work really well.

Let us know how you are getting along on this project. Have you blinked a LED on port A yet?

Archangel
- 8th July 2011, 08:20
Search here . . .

http://www.mouser.com/Electromechanical/Encoders/_/N-39xfc/

Seriously Cheap !

RayL113
- 9th July 2011, 00:38
You can use that, you can use the thing you already have, its up to you. They both CAN work. With the CB switch you will only get 16 changes per full revolution. If this is enough then use it. It will prolly still have noisey output so de-bouncing will still be neccessary. Now if you can get this (http://usdigital.com/products/encoders/incremental/rotary/kit/e4p), I have used many, they work really well.

Let us know how you are getting along on this project. Have you blinked a LED on port A yet?

I think I'm going to try to use the channel selector approach. Using RE1 thru RE4 as the inputs. I read in the manual that there is a command that will sample the designated pins and store the result in a register of my chosing. The problem I am having trouble sorting out in my head is what should I do when the count goes back to 0000 after 1111 and vice versa. And still have the count continue up or down. Is there some way to like have a loop restart when this limit is reached?
Just messing with it as time allows. So not much progress. Still learnig the PBP commands and uses. And yes, got LED's blinking like crazy using machine code, but haven't tried it wih PBP yet.
Thanks for the helps Guys!

cncmachineguy
- 9th July 2011, 01:07
well let me say I think its the more complicated way, but hey that makes it more fun. I would guess you will have to read the count on the selector, compare it to the last count, If it is higher, add 1 to the freq, if its less subtract. To cross the zero, you will have 2 choices when at 0 of at $F. from o you will go to 1 or $F, and from $F you will go to 0 or $E. So just check for that when you get to those counts.

I would think you will have to really spin the selector VERY fast to miss any counts, so I would start with that scheme and see how it works. Don't forget you may need to de-bounce the inputs.

RayL113
- 9th July 2011, 22:37
Thanks Bert. Should I use the IF...THEN string? Something like this;
Start
PEEK CHSEL CHSELVAR
IF CHSEL = 0000 THEN CHECK0
IF CHSEL = 1111 THEN CHECK1
ELSE LOOP

LOOP
PEEK CHSEL CHSELVAR
If CHSEL > CHSELVAR Then UP
Else
PEEK CHSEL CHSELVAR
IF CHSEL < CHSELVAR Then DOWN
Else
GOTO Start

UP
PLLDATA = PLLDATA +1
MOVLF PLLDATA PLLDATAOUT
GOTO Start

DOWN
PLLDATA = PLLDATA -1
MOVLF PLLDATA PLLDATAOUT
GOTO Start

CHECK0
IF CHVAR = 0001 THEN UP
IF CHVAR = 1111 THEN DOWN
ELSE LOOP

CHECK1
IF CHVAR = 0000 THEN UP
IF CHVAR = 1110 THEN DOWN
ELSE LOOP

Of course I didn't include all the defines. Am I on the right track?

cncmachineguy
- 10th July 2011, 00:14
Seems like the basic idea. Not sure what language that is but the idea looks about right

RayL113
- 10th July 2011, 06:33
Seems like the basic idea. Not sure what language that is but the idea looks about right

Uh Oh. Thought it was PBP. What did I do wrong?

cncmachineguy
- 10th July 2011, 20:29
Ray, I stand corrected. I was thinking peek came from a different language, but I see it is a valid pbp command, though according to the book not recommended.

As for the movelf, well I think that is some ask haunting you. In pbp you would just use


plldataout =plldata


So yes I still think that's the basic idea.
Oh yea, loop is a reserved word in latest release of pbp, so not a good choice for your label.

RayL113
- 11th July 2011, 00:19
Yes, I corrected that. Thanks.
Where do I find the reserved words? Looked through the manual. Couldn't find them.

cncmachineguy
- 11th July 2011, 01:13
can't answer that one, I must say I have ony read it here MANY times, so I assume it to be true. I think it might be in the front or the back in a section talking about differences from previous versions or differences from BS2. Not sure.

rsocor01
- 11th July 2011, 02:02
Where do I find the reserved words? Looked through the manual. Couldn't find them.

Look in appendix C in your manual.

http://melabs.com/resources/pbpmanual/

RayL113
- 11th July 2011, 13:47
I'm trying to assign 4 pins from PORTA as the CHSEL f/register as follows;

CHSEL = PORTA.1.2.3.4
Get this error;
C:\PBP\PLL-CPU.BAS ERROR Line 24: Bad variable modifier: .1.2.3.4
I've tried different variations on this (1-4) (1234) etc. but with the same results.
What is the correct syntax for doing this? I only want to use these 4 pins.

RayL113
- 11th July 2011, 13:48
Look in appendix C in your manual.

http://melabs.com/resources/pbpmanual/

Thanks, looked right over that.

mister_e
- 11th July 2011, 19:54
I'm trying to assign 4 pins from PORTA as the CHSEL f/register as follows;

CHSEL = PORTA.1.2.3.4
Get this error;
C:\PBP\PLL-CPU.BAS ERROR Line 24: Bad variable modifier: .1.2.3.4
I've tried different variations on this (1-4) (1234) etc. but with the same results.
What is the correct syntax for doing this? I only want to use these 4 pins.
You need to use BitWise masks for that

chsel = (PORTA>>1) & $0F

you'll need to use that line each time you want to read from PORTA.

RayL113
- 12th July 2011, 00:21
You need to use BitWise masks for that

chsel = (PORTA>>1) & $0F

you'll need to use that line each time you want to read from PORTA.

Thanks Steve.
But what is this doing? I mean is it assigning pins 1 thru 4 to the CHSEL label?
And "Bitwise Mask". I don't see that in the manual. What does it mean?
There's got to be an easier way to do this than having to insert that line every time.
What is the best way to assign input pins to a register in PBP?
For that matter, how do you assign anything to a register in PBP. Can't find that in the manual either!

mister_e
- 12th July 2011, 00:50
CHSEL VAR PORTA

This will assign the whole PORTA, all the time to chsel variable... it's a simple alias. Still, it's the WHOLE PORTA reading, you still need to remove the bit you don't want/need.

If you want to assign a single pin to a variable
A_SINGLE_PIN VAR PORTA.0

As far as I'm aware of, there's no shortcuts. Bitwise & Logical mask/operations are indeed listed in the manual, not explained as it's a basic knowledge you should already be aware of when programming. Case not, there's Wikipedia & Google
http://en.wikipedia.org/wiki/Bitwise_operation
http://www.ralphb.net/IPSubnet/logical.html
and so forth

mister_e
- 12th July 2011, 00:58
chsel var byte
'
'
'
'
chsel = (PORTA>>1) & $0F

this read PORTA, shift the whole value one place to the right (to remove PORTA.0), then isolate the 4 lower bits.

RayL113
- 15th July 2011, 06:03
chsel var byte
'
'
'
'
chsel = (PORTA>>1) & $0F

this read PORTA, shift the whole value one place to the right (to remove PORTA.0), then isolate the 4 lower bits.

Ok, so let's say then, that I don't use the lsb as the toggle pin, and use 0 thru 3 as my 4 input bits, would the command be chsel = (PORTA) %00001111 ??
Or am I missing the point?

mister_e
- 15th July 2011, 08:50
Really close
chsel = PORTA & %00001111
you're on the right direction!

RayL113
- 18th July 2011, 01:39
Really close
chsel = PORTA & %00001111
you're on the right direction!

Thanks! I'll give that a try.

RayL113
- 18th July 2011, 01:49
That worked! Thanks again.
Have another little snag.
It doesn't like my Peek command syntax.
Get this error; ERROR Line 27: Bad expression.27: Syntax error

Here is line 27; PEEK CHSEL CHSELVAR 'Line 27, Look at the 4 input pins from the channel selector and put in CHSELVAR

It appears that I'm not inputting the Peek command correctly. Anyone familiar with this command?

ScaleRobotics
- 18th July 2011, 03:25
It looks like you should have a comma:

PEEK CHSEL, CHSELVAR

cncmachineguy
- 18th July 2011, 03:33
I have a concern for you, in this bit of code


LOOP
PEEK CHSEL CHSELVAR
If CHSEL > CHSELVAR Then UP
Else
PEEK CHSEL CHSELVAR
IF CHSEL < CHSELVAR Then DOWN
Else
GOTO Start

I think your intention is to set chselvar equal to the contents of address chsel. then in the next line you test to see if they are different. So if I am following this correctly, you will have to move the channel selector at the exact moment between the peek and the IF. May work better to set a var like chselvarold then on the next loop see if chselvar = chselvarold. if = then goto start, if not decode what to do.

RayL113
- 19th July 2011, 02:43
I have a concern for you, in this bit of code


LOOP
PEEK CHSEL CHSELVAR
If CHSEL > CHSELVAR Then UP
Else
PEEK CHSEL CHSELVAR
IF CHSEL < CHSELVAR Then DOWN
Else
GOTO Start

I think your intention is to set chselvar equal to the contents of address chsel. then in the next line you test to see if they are different. So if I am following this correctly, you will have to move the channel selector at the exact moment between the peek and the IF. May work better to set a var like chselvarold then on the next loop see if chselvar = chselvarold. if = then goto start, if not decode what to do.

What about if I don't recheck with Peek and do this instead;
CHLP:
PEEK CHSEL, CHSELVAR 'Look at the 4 input pins from the channel selector
If CHSEL > CHSELVAR Then UP 'if it's larger then run subroutine UP
IF CHSEL < CHSELVAR Then DOWN 'if it's smaller then run subroutine DOWN
GOTO Start 'if neither are true then goto start

What do you think?

RayL113
- 19th July 2011, 02:45
That worked great! Thanks

RayL113
- 19th July 2011, 02:46
It looks like you should have a comma:

PEEK CHSEL, CHSELVAR

Adding the comma worked great! Thanks

RayL113
- 29th August 2011, 17:41
Got that working! Thanks for the tip,
Now on to the display. 3 digit 7 segment display, common cathode.
I want to take the port C pin states and look those up in a table.
Then Send the table contents at that address to the 3 digit display.
I've been reading post and looking at some lookup codes but to be honest, I don't know where to start.
I think I know what I want in the table but getting it to the display is where I'm getting confused.
Any suggestions?

Dave
- 29th August 2011, 20:25
Rayl113, I assume the display is going to be multiplexed as all you are using is port c? Is it going to have latches for the digit data or is it going to be some kind of serial display?

RayL113
- 30th August 2011, 00:47
Rayl113, I assume the display is going to be multiplexed as all you are using is port c? Is it going to have latches for the digit data or is it going to be some kind of serial display?

The display is laid out like this;
RB0=A
RB1=B
RB2=C
RB3=D
RB4=E
RC0=F
RC1=G
RC2=dp
RC3=Digit-1
RC4=Digit-2
RC5=Digit-3
RC6=Digit-4(future)
RC7=Digit-5(future)

I'm using NPN transistors to switch the digit commons to ground.
It would probably be a good idea to latch in the display data but I'm not sure how to proceed.
It's mostly learn by trial and error at this point.

Dave
- 30th August 2011, 17:42
Rayl113, I have attached an old program that you can use parts of or simply as a template to understand the workings of a multiplexed display using a pic. I hope this helps. I found an old hallway clock from a school and backward engineered the circuit. I just had to as the clock has 5 inch 7 segment digits. It used a pic processor so, I redesigned the software to accomodate the already designed circuit. Works Great....

RayL113
- 31st August 2011, 12:27
Thanks. I think I got that part figured out;
Display:
'Segment A = PORTB.0
'Segment B = PORTB.1
'Segment C = PORTB.2
'Segment D = PORTB.3
'Segment E = PORTB.4
'Segment F = PORTC.0
'Segment G = PORTC.1
'Segment dp = PORTC.2
'Digit1 = PORTC.3
'Digit2 = PORTC.4
'Digit3 = PORTC.5

Where I'm stuck is building the tables and selecting the information to send to each digit. I have a spreadsheet with the values already calculated.
I want to sample PORTD and use that as the address of the info I want to send to the digits.
e.g., If PORTB = $3F, I want to use Address $3F as a pointer within the table and pull the info from that location and send it to the digits. Let's say "C19".
I need "C" in digit 1, "1" in digit 2, and "9" in digit 3.
This is where I'm stuck. The manual is really lacking when it comes to creating Lookup tables. I've looked at some of the example files, but gotten more confused.
So any help on this would be appreciated.

Dave
- 31st August 2011, 22:16
Rayl113, It is possible, as you can have a table that is upto 255 entries in size maximum. An easy way is to have 3 tables, one for each digit and then use the "3f" entry as the index. The output of each table would be the digit value to display. The other way is to use a table that outputs "word" values. That way you only have one table for the lookup, indexed by a byte value from "00" to "ff" and outputs the word. That way the word can have a value equal to between "0000" and "ffff" . The entries into the table for the output could be the 3 digit hex representation of the display such as "C19".

RayL113
- 4th September 2011, 19:31
Rayl113, It is possible, as you can have a table that is upto 255 entries in size maximum. An easy way is to have 3 tables, one for each digit and then use the "3f" entry as the index. The output of each table would be the digit value to display. The other way is to use a table that outputs "word" values. That way you only have one table for the lookup, indexed by a byte value from "00" to "ff" and outputs the word. That way the word can have a value equal to between "0000" and "ffff" . The entries into the table for the output could be the 3 digit hex representation of the display such as "C19".

I got it working by using 3 tables. Thanks. I never could get the word version to work. It only gave me 16 bits and I needed 24. Haven't tried the long word version yet. That's next.

Now I need to set the FOSC bits in the CONFIG1H register to 0010. I'm sure it's a CON command. But don't know which one. Any help appreciated.

Dave
- 6th September 2011, 22:32
Rayl113, I'm glad you got it working, I just got back from a vacation with the wife and kids. We did some serious shooting and the wife likes gun's now... Yipeeeee

RayL113
- 9th March 2012, 09:42
Trying to get my code to run on a PIC18LF2680. When I step thru the code I notice it skips over all of the "VAR" statements.
However, when I continue, it acts like it is performing the required instruction. But when I try to run stand-alone, it doesn't work. I can see with an O'Scope that the clock is working but no I/O activity.
Here's the config code;
#CONFIG
__CONFIG _CONFIG1H, _OSC_HS_1H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
;Set osc, Low-Voltage Programming disabled,
;Extended Instructionset disabled,
#ENDCONFIG
Define OSC 4 ' 17
' 18
TRISA = $00 'set port a to all outputs ' 19
TRISB = $00 'set port b to all outputs ' 20
TRISC = $FF 'set port c to all inputs ' 21
LATB = $00 'clear port b latches ' 22
PLLDATA Var Byte ' stores value for PLLDATA ' 28
LASTCH Var Byte ' stores value for LASTCH ' 29
PLLDATAOUT var byte 'stores ouput for portB ' 30
CHSEL Var Byte 'channel selector storage ' 31
Display Var BYTE 'Display storage ' 32
Char1 VAR BYTE 'Digit 1 transistor switch ' 33
Char2 VAR BYTE 'Digit 2 transistor switch ' 34
Char3 VAR BYTE 'Digit 3 transistor switch ' 35
LASTCHSEL Var Byte 'stores the previous position of the ch selector ' 36
SEGSW Var BYTE ' 37
LOGOCNT Var BYTE ' 38
Digit3 Var PORTA.0 ' 41
Digit2 Var PORTA.1 ' 42
Digit1 Var PORTA.2 ' 43
BNDDNSW Var PORTA.3 ' 50
BNDUPSW Var PORTA.4 ' 51
LTCHENBL Var PORTA.5 'Latch Enable ' 46
'LTCHENBL = 0
CHSEL = PORTC & $0f 'set the inputs for the channel selector register ' 57
READ 5, LASTCH 'Read the last channel data from the EEProm 58
IF LASTCH = $FF THEN LASTCH = $70 'power up ch = CH 16 (Call channel) ' 59
IF LASTCH = $00 THEN LASTCH = $72 'power up ch = Ch 18 (Coast Guard) ' 60
PLLDATAOUT = PLLDATA 'put PLLDATA on the output pins ' 121
PORTB = PLLDATAOUT
LTCHENBL = 1
LTCHENBL = 0
PORTB = Display
LOGOCNT = $a0 'set the countdown timer for logo display ' 65
Start:

Is there something else I need to do in the configuration statement?
Thanks

ScaleRobotics
- 14th March 2012, 13:23
This may not be it, but the only thing I notice is: you have OSC_HS selected, but you are using an oscillator at 4 mhz. If you are using an oscillator instead of a resonator, this should be set to XT for 4 mhz. If you are using a resonator, did you see the note with the data sheet?



Note: When using resonators with frequencies
above 3.5 MHz, the use of HS mode,
rather than XT mode, is recommended.
HS mode may be used at any VDD for
which the controller is rated. If HS is
selected, it is possible that the gain of the
oscillator will overdrive the resonator.
Therefore, a series resistor should be
placed between the OSC2 pin and the
resonator. As a good starting point, the
recommended value of RS is 330Ω.

Dave
- 14th March 2012, 17:40
Rayl113, Also make sure the "PBADEN" bit's are set for Digital on reset. Other wise the port Bb.0 thru B.3 are set as analog after reset....