PDA

View Full Version : The worst programmer ever to grace this forum - ME!



HankMcSpank
- 14th March 2009, 00:29
Ok, I've been on about 8 hours trying to get a damn LED to light using PICBAsic - nothing!

I have a PICkit 2 (the board comes with a PIC16F690), everything works fine with 'hello world' tutorial Microchip provide (which proves the chip & LED is fine). Assembly language make my brain spontaneously combust so I would like to learn a higher level language such as basic (which seems at least a little akin to DEC DCL...something I used about 10 years ago)...I'm beginning to wish I hadn't.


Right to my simple problem - more than anything in the world right now, I want to see that stupid little LED on my PICkit 2 low pin count board light up!

Most of the 'flash an led' example basic programs work on the PIC's Port A...now I thought it would be a simple case of changing the references conatined therein to PortC (the 4 leds on the Pickit board are attached to Port C)

But when I change not a lot happens!

I'm aware that the 16f690 has analogue ports turned on as default & Ive seen some mention that this can be remedied with a commands along these lines

ANSEL = 0
ANSELH = 0

but the microcode studio GUI doesn't seem to recognise those commands (I'm new to this interface but it seems to darken/bold commands it's happy with)

Could some one humour me here & cut/paste in the ludicrously simple basic code for PIC Basic Pro that I need to light an LED on portc.1 of my 16f690.

I can then put this all to rest & pour petrol over my pickit 2 whilst moonwalking backwards to "The eye of the Tiger".




FWIW, This is the latest code I've tried (based on this link http://www.digital-diy.net/16F%20Examples/16F_LED's.aspx )....

Symbol LED_1 = PortC.0 ' Define a symbol in the program

TRISC.0 = 0 ' Make PORTC.0 an output
PORTC.0 = 0 ' and set it low (0V)

Main:

If LED_1 = 0 then ' Check the status of the LED
LED_1 = 1 ' and toggle it
Else
LED_1 = 0
Endif

DelaymS 1000 ' Delay for 1 second (compiler errors with this line - I guess the command isn't right!)
Goto Main ' Loop forever




Basic Schhmasic....

Archangel
- 14th March 2009, 00:50
Here, this chaser works with the hardware you are using:
MPASM required, you must comment out the config in the .inc file for 16f690 in PBP root.


@MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON
@MyConfig = MyConfig & _MCLRE_ON & _BOR_OFF
@ __config MyConfig

DEFINE OSC 4
PortA = 0
PortB = 0
PortC = 0
TRISA = 0
TRISB = 0
TRISC = 0
i var byte

main:
portc = 0
pause 500
for i = 1 to 15; step -1
portC = i
i=i << 1
pause 250
next i
goto main
end

Here's a blinkey:


DEFINE OSC 4
PortA = 0
PortB = 0
PortC = 0
TRISA = 0
TRISB = 0
TRISC = 0

LED_1 var PortC.0 ' Define an alias in the program
led_1 = 0

Main:
HIGH LED_1
PAUSE 1000
LOW LED_1
PAUSE 1000
Goto Main ' Loop forever
end

OK here is your code reworked:


DEFINE OSC 4
LED_1 VAR BIT ' PORT FLAG BIT
LED_1 = 0 ' SET INITIAL VALUE
TRISC.0 = 0 ' Make PORTC.0 an output


Main:
IF LED_1 = 0 THEN
LED_1=1
ELSE
LED_1 = 0
ENDIF
PORTC.0 = LED_1




PAUSE 250 ' Delay for 1 second (compiler errors with this line - I guess the command isn't right!)
Goto Main ' Loop forever

It appears as though the PIC cannot read and change it's own output without an intermediary like a flag variable. Probably
A RMW thing, I do not know.

HankMcSpank
- 14th March 2009, 10:14
Ok, many thanks for helping me.

When I enter the code you recommended below *and*comment *all* the entries in the 16f690.inc (c:\PBP) I get 121 compiler errors (I have MPASM selected under the assembler tab ...I'm using the defaul selections when I select MPASM eg INHX8SM)...


@MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON
@MyConfig = MyConfig & _MCLRE_ON & _BOR_OFF
@ __config MyConfig

DEFINE OSC 4
PortA = 0
PortB = 0
PortC = 0
TRISA = 0
TRISB = 0
TRISC = 0
i var byte

main:
portc = 0
pause 500
for i = 1 to 15; step -1
portC = i
i=i << 1
pause 250
next i
goto main
end

but when I reenable all the comments in the .inc file, i only get 2 errors (relating to line 63 in the corresponding asm file - if my counting is correct, it's this line __config MyConfig ....is there an easier way to establish the line that's erroring from what's being reportred in the results field?)

mackrackit
- 14th March 2009, 10:18
When I enter the code you recommended below *and*comment *all* the entries in the 16f690.inc
http://www.picbasic.co.uk/forum/showthread.php?t=543

HankMcSpank
- 14th March 2009, 13:49
To me, that FAQ assumes a fair degree of previous knowledge!

if I'm reading it right, the 16F690.inc file tells the assembler to configure the PIC for 'what's out there'?

What's doing my head in is the sheer number of 16f690.inc files there are on my PC...

c:\mpasm\16f690.inc (which looks a whole lot different to the others!)

c:\pbp\16f690.inc (the one that Joe S said I should comment out - not sure which lines ...all of them?)

c:\pbp\inc\ (a whole lot of files in here!)


At the risk of sounding incredibly slow - help!

Once again, all I want is the correct code to 'set the chip correctly' for me to then start my simple journey to get an LED, firstly lit, then flashing (wheee!)

Joe.S kindly posted a 'chaser' earlier ( & said I needed to comment out the inc file in c:\pbp ....which lines?!)

I'm perplexed that this chip should be so troublesome at the very first base ....from a newbie's perspective, it's probably the most prevelant since it's bundled in with the low pin count board on on the Pickit 2 starter. It might have been useful to have a "So you got a 16F690 PIC & you've arrived here after using the Pickit 2....here are some things you should know/do!" type thread.

I'm an absolute novice here.....are we saying there's an issue with the PIC itself...or just this particular PIC in combination with PICBasic? (fwiw, I'm suspecting the latter as the PIC is fine using the Micropchip Assembler)

Many thanks in anticipation.

Bruce
- 14th March 2009, 14:46
In your 16F690.INC only comment out the __config line. Leave everything else
as-is.

Then something like this should work if you're disabling analog inputs & comparators;


@MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON
@MyConfig = MyConfig & _MCLRE_ON & _BOR_OFF
@ __config MyConfig

DEFINE OSC 4

i var byte

ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0
PortC = 0
TRISC = 0


main:
portc = 0
pause 500
for i = 1 to 15
portC = i
pause 150
next i
goto main
end

HankMcSpank
- 14th March 2009, 15:03
Hey Bruce...that compiled without errors! (which is progress in my books! A big thanks to Joe.S too, as it's pretty much as he said...just naivity wrt commenting out the inc file on my part)

Can someone explain what's actually going on with the looping part though....

main:
portc = 0
pause 500
for i = 1 to 15
portC = i
pause 150
next i
goto main

It looks like it's setting port C output to be low, waiting 500 (milliseconds?), the making PRT C = i .....what's that "i" melarkey all about?!!


Still no sign of life from the LED on my PICkit 2 board though (though I'm figuring Port C needs to be set high at some stage ....by the way, why no use of PORTC.0 or PRTC.1 here...ie nominating the actual chip pin RC0, RC1 etc?)

tks,
Hank.

Archangel
- 14th March 2009, 19:18
Can someone explain what's actually going on with the looping part though....

main:
portc = 0
pause 500
for i = 1 to 15
portC = i
pause 150
next i
goto main

It looks like it's setting port C output to be low, waiting 500 (milliseconds?), the making PRT C = i .....what's that "i" melarkey all about?!!


Still no sign of life from the LED on my PICkit 2 board though (though I'm figuring Port C needs to be set high at some stage ....by the way, why no use of PORTC.0 or PRTC.1 here...ie nominating the actual chip pin RC0, RC1 etc?)

tks,
Hank.
Last things first, The code assumes the port arrangement is from lowest order portc.0 to highest order portc.7 in its display of count. The i is just a name for the variable storing the count, you can rename it HankMcSpank and it will work the same, it is just easier to use i. So you have a variable storing a binary count to 15, the i=i<<1 is there to alter the light sequence so you do not have any dark leds in between lit ones. Try commenting it out and you will see it count in binary. Change the 15 to seven and it will only light 3 LEDs.
<br> Now as for no signs of life from your LEDs, in the PICkit2 programmer software there is a check box that must be selected to power your demo board, unless you rig a separate power line to it.
<br>__config MyConfig is a trick I picked up from Darrel so as to avoid having my config statement run off the reservation (the page). This is especially helpful if you print your code for archival purpose. You can, and most do put it all on one line like so:<br>@ __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _BOR_OFF

Edit: I initially misunderstood last question.

HankMcSpank
- 14th March 2009, 20:00
<br> Now as for no signs of life from your LEDs, in the PICkit2 programmer software there is a check box that must be selected to power your demo board, unless you rig a separate power line to it.

VDD *is* present (ie I double checked, by testing the VDD test point with my Voltmeter ....when I added the Pickit 2 to PICBASIC, I quickly established that -T needed to be added to the parameter field to keep VDD on the board when the programming sequence exited.

My LEDS are doing anying!

Could you please outline what bit of code would need to follow your 'chaser' to raise all RCx ports high? ...

@MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON
@MyConfig = MyConfig & _MCLRE_ON & _BOR_OFF
@ __config MyConfig

DEFINE OSC 4
PortA = 0
PortB = 0
PortC = 0
TRISA = 0
TRISB = 0
TRISC = 0
i var byte

....I'll settle for *any* illuminated LED at this stage! (flashing or not).

The PICkit 2 board has an LED connected to pins RC0-RC3. (btw: I can handle references like PORTC.0 PORTC.1 ...but at this stage, I'm just not locking in to referencing the Port C pins on the PIC in other ways!)



PS As a sanity check, I've just programmed up the PIC with the Microchip "rotate" hex code....all LEDs light up & chase just fine.

mackrackit
- 14th March 2009, 22:10
_MCLRE_OFF
???
I do not have the board you have, just maybe..

HankMcSpank
- 15th March 2009, 00:09
_MCLRE_OFF
???
I do not have the board you have, just maybe..

:D BINGO! That was it!!! Many thanks to you all!!

For the record, anyone else with a PICkit 2 board (with a PIC16F690) .....to save you hours of puzzlement...

In your C:\PBP\16F690.INC , comment out this one line (thanks to Bruce)...

; __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF

Put all of the following code at the top of your PICBASIC programming window (thanks to mackrackit for the _MCLRE_OFF tip)...

@MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON
@MyConfig = MyConfig & _MCLRE_OFF & _BOR_OFF
@ __config MyConfig

DEFINE OSC 4

i var byte

ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0
PortC = 0
TRISC = 0


And if you have - like I have - a burning desire to see your board's LEDs light in sequence, add this bit of code (thanks to Joe.S)...

main:
portc = 0
pause 500
for i = 1 to 15; step -1
portC = i
i=i << 1
pause 250
next i
goto main
end


What's a beginner to do?!!! Most of this was (is!) double dutch....a what with a day & a half's effort just to get LEDs lit with the simplest of basic code....I think my programming interest is going to wane very fast!.

Now to my main intention, a simple PIC based 'pulse counter' program for a coil winder.

If your interested, you can read about what I'm trying to achieve here ....

http://www.electro-tech-online.com/micro-controllers/90245-simple-pulse-counting-pic-program-needed.html

(you can see my appeal for the simple PIC program didn't get much of a response, hence me having to darken this forum's doorstep and try to figure it all out myself!)

Archangel
- 15th March 2009, 01:03
Huh, that's funny, I copy pasted that from MCS on my computer, and it works splendidly with MCLRE_ON, I can reset MCLRE on the programmer using the little check box and that works too.<br>
Glad Dave got you going !

HankMcSpank
- 15th March 2009, 09:57
Just got hit with the next 'gotcha'!

I was trying to get an LED to light up when the button on my low pin count was pressed - just spent ages trying to figure out why the LED wouldn't light. A check with my voltmeter revealed no matter code I tried, RA3 was always held low, a bit of Googling revealed this...

http://www.microchip.com/forums/tm.aspx?m=270347


F: Pushbutton doesn't work with Low Pin Count (LPC) or 28-Pin Demo Boards
The pushbutton cannot be used on these demo boards when debugging or programming and powering them from the MPLAB IDE. The pushbutton switch is connected to the input pin that is shared with the nMCLR/VPP pin. When Debugging, this pin must be used as nMCLR and cannot be used as an input pin. When programming and leaving the PICkit 2 connected to the Demo Board to power it, the MPLAB IDE always maintains a valid output state on a programmer's nMCLR/VPP pin which prevents the switch from changing the signal value. Use the PICkit 2 Programmer software to allow the switch to be used.

It seems I now have to assemble, & then fire up PICKit 2 to wrtie the hex to the PIC (button works as it should then).

Mindboggling for a beginner like me, ie that there should be so many 'enviromental' hurdles to get over, when all I want is to learn the most simple of code!

mackrackit
- 15th March 2009, 12:54
I will suggest you pick up a cheap bread board or two and a hand full of LEDs, resistors, caps etc. The demo boards are nice I guess, but you can not do a whole lot with them other than what they were designed to do.

As far as the coil winding project goes. A switch on a cam or some other part will work. Every revolution the switch is "bumped" from low to high. Every time the switch is bumped a variable is incremented.

If it is not running real fast interrupts will not be needed.


LOOP:
IF SWITCH = 1 THEN
WRAP = WRAP + 1
GOTO LOOP

That is the basics. Add a serial or LCD to display the value. Add
IF WRAP = X THEN GOTO STOP ???

Let us know...

HankMcSpank
- 15th March 2009, 13:23
I will suggest you pick up a cheap bread board or two and a hand full of LEDs, resistors, caps etc. The demo boards are nice I guess, but you can not do a whole lot with them other than what they were designed to do.

As far as the coil winding project goes. A switch on a cam or some other part will work. Every revolution the switch is "bumped" from low to high. Every time the switch is bumped a variable is incremented.

If it is not running real fast interrupts will not be needed.


LOOP:
IF SWITCH = 1 THEN
WRAP = WRAP + 1
GOTO LOOP

That is the basics. Add a serial or LCD to display the value. Add
IF WRAP = X THEN GOTO STOP ???

Let us know...

Whilst I was sold on the concept of the ease of use of the Microchip low pin count board, (esp to get me some simple quick & dirty IO) I'm now very rapidly seeing the shortcomings!

As it goes I have, breadboard & plenty of components...I'll be using all that in earnest, once I've nailed the basics here (no pun intended).

Re the coil winder. I'm using an old DC cooling fan with a drill chuck hot glued to its centre ( http://img25.imageshack.us/img25/2717/workshopjd8.jpg - ugly but fulfills a need!)....this drill chuck will hold the 'solenoid core' while to copper wire is wound onto it. On this fan will be 7 or so magnets, each in turn closing a magnetic reed switch as the motor turns (I'd imagine the maximum speed the fan will be turning at for this project will be about 200RPM I've made a simple PWM circuit to control the speed of the fan).

Where the PIC comes into the equation, is that it will count the pulses from the fan motor. For every 'X' pulses it receives from fan motor's reed switch, the PIC will send one short pulse onwards to a UCN5804 stepper motor IC. It's essentially a pulse counter/divider ...for ever x pulses received, output one pulse.

The UCN5804 feeds a small stepper motor - on its shaft is a bit of threaded nylon rod - it's over this threaded rod that the copper wire feeds onto the solenoid core (this youtube video illustrates what I'm trying to achieve well - http://www.youtube.com/watch?v=Q_Cd_5zTt9w (from about 27 seconds in).

The whole point of this is to have my wire neatly wound onto the solenoid. Since I know the diameter of the copper wire (0.15mm), & I know the pitch of the nylon rod's thread feeding the wire (1mm), it's just a fairly simple calculation. therefore for every turn of the main DC fan, I need the stepper motor threaded rod traverse the wire 0.15mm. It's a 7.5deg stepper, therefore each step of the 1mm pitch threaded rod will traverse the copper wire 0.0208mm, therefore to move the wire 0.15mm, some 7.2 steps needed are to the stepper for every turn of the main fan (since there's no such thing as 0.2 of a pulse I'll be rounding it down to 7!)

To nail this project I need to...

1. Sort out all the idiosyncracies of getting my PIC programming enviroment set up for the PIC16F690 - check! (thanks to here!)
2. Lean how to set a PIC output pin high - check!
3. Learn how to check a PIC input pin (to see if a switch has closed) - check!
4. Learn how to setup a few 'count' variables, get them incrementing (& check 'em)....acting whenever the counts have been met - still to do!
5. Learn how to output a pulse - still to do.

I'll also need to figure out some form of debounce (I may end up using a monostable chip to do this)

Thanks for your suggestion on how to approach this...I'll have a play with your lines to see if I can get the switch on my low pin count board to act as the reed switch & one of the LEDs as the stepper chip feed....ie after 7 presses of the board's button, make an LED turn on.

nomad
- 15th March 2009, 16:37
do the debounce in software. (short pause) or if it's off to do something else once triggered, you may not even need debounce..

you can search for debounce examples from here http://www.picbasic.co.uk/forum/showthread.php?t=4751

HankMcSpank
- 16th March 2009, 00:35
Ok, a bit more reading .... it seems the button command will be perfect for needs.

My initial problem is that it only acts on PORTB pins (& the Pickit 2 board has its switch wired to RA3). therefore I've rigged up a pull up resistor onto pin RB7 & a small switch which goes to ground (therefore puts 0V onto RB7 when this new switch pressed). However RB7 is being held low all the time.

I'm figuring this must be something to do with the .inc file again (I've rechecked my wiring - it's fine ...10k resistor between RB7 & the 5V rail....and a normally open switch going from RB7 to ground). I chose RB7 for my new switch as it seemed to have the least happening! On the datasheet it's listed as RB7/TX/CK ...how can I be sure it's being used as an input pin only (& not being overridden by one ithe pins other purposes)

Does anyone have any ideas why my RB7 might be permanently low.

Here's the small bit of code I'm using...

@MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON
@MyConfig = MyConfig & _MCLRE_OFF & _BOR_OFF
@ __config MyConfig

DEFINE OSC 4
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0 ' dunno what this line does!
CM2CON0=0 ' nor this one!
TRISA=%11111111 ; set all Port A pins as inputs
TRISB=%11111111 ; set all Port B pins as inputs
TRISC=%00000000 ; set all Port C pins as outputs

B0 VAR BYTE ;creates a variable as needed for the button command below
B0 = 0 ; give it a value of zero (as per the command's reference)

LED1 var PortC.0 ' ; assign a more usable name to the first LED port

start:
LOW LED1 ; turn the first LED off

BUTTON 7, 0, 255, 0, B0, 1, Loop ; monitor the switch on RB7 for 0V,
;if this condition is net, then go to next

next:
high LED1 ; turn the first LED on
PAUSE 1000 ; wait one second
goto start ;start over
End

mackrackit
- 16th March 2009, 02:48
BUTTON 7, 0, 255, 0, B0, 1, Loop
???????
Try
BUTTON PORTB.7, 0, 255, 0, B0, 1, Loop

Or better yet


IF PORTB.7 = 0 THEN GOTO NEXT

OOPS!!!!!!
That will not work...NEXT is a reserved word. Will have to think of something else to call that label.. FRED??

GregYent
- 16th March 2009, 04:11
HankMcSpank,

I think the 'F690 is going to be my next favorite PIC. It has SO MUCH STUFF on it!
In other words, not a beginner PIC ( like the 16F628, F648, F87, F84(old and gray) )
There are ALOT of registers to learn how to use on this chip.

NOTE: something that used to trip me up when reading data sheets:
when you "SET" a value you change it to "1"
when you "CLEAR" a value you change it to "0"
so that if someone says "set the flag", it means to ONE, (1), HIGH
I only bring this up because you are new. The M-chip data sheets use this nomenclature all the time.

Also NOTE: The 16F690 Datasheet is your new best friend. All 306 pages, WOW. You might want to print out the pages with
the register descriptions for each "feature" so you know what CM1CON0, etc means. Adobe pages 34-37 are best. Also,
under the feature headings are listed all relevant registers that need to be set/cleared, usually near the end.

You might need to set ( or CLEAR) the following registers as well (some required in other PICs):

'Registers:
ANSEL = %00000000 ' clears the individual bits that select analog inputs (low register)
ANSELH = %00000000 ' clears the individual bits that select analog inputs (high register)
VRCON = %00000000 ' turns the Vref Module OFF by CLEARING bit7, 6, 4

'I use the binary format so I can easily set them later. I know it seems redundant when they are all 0's, but later....

'Bits Only:
CM1CON0.7 = 0 ' turns Comparator1 OFF by CLEARING bit7
CM2CON0.7 = 0 ' turns Comparator2 OFF by CLEARING bit7
ADCON0.0 = 0 ' turns the AD Converter OFF by CLEARING bit0
INTCON.0 = 0 ' clears the RABIF Flag (to 0), COULD be 1 on reset (unique to F690)
RCSTA.7 = 0 ' clears the SPEN bit ( SETTING SPEN DISABLES RB7 AS GENERAL PURPOSE! )
'note that there is an Errata Datasheet that mentions issues with SPEN, but only when using the Serial Hardware

'you might HAVE TO do this after clearing ANSEL/ANSELH
PORTA = %00000000 ' Clear the port register latches
PORTB = %00000000
PORTC = %00000000

TRISA = %11111111 ' Set or Clear the data direction registers
TRISB = %11111111
TRISC = %00000000

'FOR EXAMPLE: On the F628 and friends, you only need:
'CM1CON = 7 ' turns the comparators OFF by SETTING bits 0,1,2
'and the Port/Tris settings

'OK, now on to your code...
'The Button Command:
BUTTON 7, 0, 255, 0, B0, 1, Loop
'"7" is not a pin name.
'For buttons and LEDs, I use names like btnStart or btnUp, LEDFault, LEDStatus.
'But sometime I use PHYSICAL pin numbers on new chips that I'm learning. So try :

RB7pin10 VAR PortB.7

'I wouldn't use the term B0 as a variable, it is used so many other places (mainly STAMP) to denote PortB.0. Try:

Temp VAR BYTE

'Also, for the Jump To label you use "Loop", but I don't see it in your listing. Maybe you meant "Next", but you can't use that name.
'So Now:

Start:
LED1 = 0

Button RB7pin10, 0, 255, 0, Temp, 1, Blink

GOTO Start

Blink:
LED1 = 1
Pause 1000
GOTO Start
End

'I'm not at work so I can't test this until tomorrow.:o

HankMcSpank
- 16th March 2009, 14:36
BUTTON 7, 0, 255, 0, B0, 1, Loop
???????
Try


Well, the command & it's example syntax it was lifted from here (page 104)....


http://books.google.co.uk/books?id=XYwuCq5u2oEC&pg=PA103&lpg=PA103&dq=picbasic+button+command+portb+only&source=bl&ots=d9Yv3ci-V4&sig=TmT3qGL9fdSPnfFxNlLRR51dhFY&hl=en&ei=I4O9SZf1DYzFjAevsfSlCA&sa=X&oi=book_result&resnum=1&ct=result#PPA104,M1

I figured that since the button command *only* wokds on PortB, that nominating ust the number 7 (as opposed to RB7) would be ok. certainly the example that link gives justiuses the number 7 too!

Greg...many thanks for the lengthy reply - i'll give that a shot tonight (I'm at work right now too!)

mackrackit
- 16th March 2009, 14:49
Well, the command & it's example syntax it was lifted from here (page 104)....


http://books.google.co.uk/books?id=XYwuCq5u2oEC&pg=PA103&lpg=PA103&dq=picbasic+button+command+portb+only&source=bl&ots=d9Yv3ci-V4&sig=TmT3qGL9fdSPnfFxNlLRR51dhFY&hl=en&ei=I4O9SZf1DYzFjAevsfSlCA&sa=X&oi=book_result&resnum=1&ct=result#PPA104,M1

I figured that since the button command *only* wokds on PortB, that nominating ust the number 7 (as opposed to RB7) would be ok. certainly the example that link gives justiuses the number 7 too!

Maybe you should read the manual that came with your copy of PBP. You will see that these book writers do not always know what they are talking about.

GregYent
- 16th March 2009, 17:40
I'm not sure that the Button Command "only works on PortB". Every other command works on any pin except the hardware modules (HPWM, HSERIN, etc).

Besides you can always use:

If btnTest = 0 then Blink 'did I change the button name? oops

Of course there is no debounce, but this is good for testing. Actually, your 1sec delay for the LED is a great debounce! nothing else is going to happen during that interval, nothing. You could also do this to BLINK as long as you hold the button down:

Start:

WHILE btnTest = 0
LED1 = 1
Pause 500
LED1 = 0
Pause 250
WEND

GOTO Start

HankMcSpank
- 16th March 2009, 18:26
Greg,

Just had a chance to try out your suggestions - it works! (iepin 10 is now high...at this stage, I can't be sure which one of those tips you gave was the one that nailed it, becuase I used them all!)

Some excellent ideas you've given there too about my main program ...in fact, I reckon I've enough sufficient info get this little program sorted now.

Many thanks to all who took the time to help me out....the internet working at its finest.



mackrackit...it was very late, & I'd just quickly googled my problem (as I always do when I have a problem & as a beginner, a search engine often serves me better as I can phrase a question when I'm not totally sure of what I'm asking!)...Google led me to that online PICbasic book & I took it at face value!

Lesson learned.

mackrackit
- 16th March 2009, 18:36
Places to get help. for PBP.

Micro Chip web site for data sheets, other places may not have the current one.
Melabs web site, can not beat the source for examples.
rentron.com - Bruce's web site. Very good examples.
This forum, Darrel has a google search in the FAQ section.

When you are ready for advanced stuff go to Darrel's web site.

Any place else and who knows...

HankMcSpank
- 27th April 2009, 23:26
I've just realised that my little program which counts the number of time a switch has been closed (a magnetic switch, which is closed as 10 successive magnets glued to the perimeter of a DC fan motor pass it by!)...isn't counting correctly - & I don't know why (though I suspect it';s either down to the debounce paramters or perhaps the length of time taken to 'do stuff' in between successive magnets).

here's my simple code (stripped down for clarity)...

RB7pin10 VAR PortB.7 ;explicity name the switch pin for button command.
RA3pin4 VAR PortA.4 ;explicity name the switch pin for button command.
Temp VAR BYTE ; this is used for debounce/delay of the fan switch)
total_counter VAR WORD ; this will count the total pulses rx'ed from magnets.
pitch_counter VAR BYTE ; this will utlimately derive the pitch thread (a divider)
direction_counter VAR word ; this will changed traversal direction word for counts bigger than 255
pulse VAR PortC.0 ; stepper feed pin 16 (to pin 11 on stepper IC)
direction var PortC.1 ;direction level pin 15 (to pin 14 on Stepper IC)


stepper_enable VAR PortC.3 ; Pin 7 this logic level 0 enables the stepper IC (stepper IC Pin 15)

Start:

total_counter = 0 ; make sure we start from zero
direction_counter = 0 ; make sure we start from zero
direction = 1 ;we want the feed stepper to move left/right first.
low stepper_enable ;enable the stepper chip.

Main:
Button RB7pin10, 0, 255, 0, Temp, 1, magnetic_switch_closed ; monitor the magnetic switch
goto Main ;if switch not closed, loop until it does close.

magnetic_switch_closed: ;ok, so switch is now closed - let's count!
total_counter = total_counter +1 'increment counter to track number of magnets passing switch.
IF total_counter = 500 THEN
goto finish ' if using 10 magnets, after 50 turns of the motor exit the program
endif
pulse_the_stepper:
pulsout Pulse, 20 ; pulse the stepper on Port C.0 with 20us pulse.
Goto main ;return to start & monitor for the switch being closed again

finish:
HIGH stepper_enable ;disable the stepper chip
End



So to my question....

Is there a more scientific way to approach this?

The motor starts off slow, & then increases under manual control up to a speed somewhere between 150RPM & 350RPM. So the rate of magnets passing the switch can be anywhere between 0 per second & 58 passes per second (350/60 = 5.8 turns per second...there are 10 magnets)

ShaneMichael
- 28th April 2009, 02:31
I see a couple of things that make me wonder, your "Temp" Var should be set to 0 at the beggining before you call "Button", if not "Button" won't work correctly.

Also, you are looking for a switch being closed at rates up to 58 times per second. 1/58 = 17 ms, so ever 17 milli seconds a magnet will sail past your switch, closing it for a moment, then it will re-open. If your magnets cover 50% of the circumference that would give you a 50% duty cycle. So the switch would be closed for 17/2 = 8.5 ms and open for 8.5 ms. In reality, your switch is probably closed about 10 % of the time or 1.7 ms.

In your code :


Button RB7pin10, 0, 255, 0, Temp, 1, magnetic_switch_closed

You have delay set at 255, this will perform debounce, but no auto repeat.

Default debounce is 10 ms, so the switch needs to be closed for 10 ms before you go to "switch_closed"

You might try a delay of 0, this shuts off the debounce.

Also you can change the debounce delay:

DEFINE BUTTON_PAUSE 1 'set button debouce to 1 ms

1 ms is still cutting it close.

Or you can skip the button all together and just read the port, something like:


If RB7pin10 = 0 Then switch_closed

You can read the state of the switch again in the "switch_closed" code, if it's still closed continue, if not jump back out. That performes a high speed debounce. You can also use PAUSEUS before you double check, so you can wait a couple of micro seconds then double check the switch is really closed.

Just some idea's.

Shane

Archangel
- 28th April 2009, 03:48
Hi Hank,
Why not just use count statement, store count in a variable ?
Looks like you want to find the end of each revolution and then increment the feed over so the wire does not overlap, yes?

ShaneMichael
- 28th April 2009, 06:28
just another thought on my last post. If you check the state of "magnetic_switch_closed" and jump into you're code where you increment your counter. Before you jump out and look for it being closed again, you should look for it to be open.

If not then you could count the same swith close multiple times all for the same instance.

something like:


if RB7pin10 = 1 then main ' make sure the switch opens before looking for another close
Else stay in loop...

Shane

HankMcSpank
- 28th April 2009, 10:41
Firstly ....Shane/Joe, thank you for taking the trouble to respond (esp to a basket case of a kludger like me!)

Ok, to your points...

Shane you are right about the temp variablle needing to be set to zero...I didn't post up that bit (my program has a lot of variables going on, but I stripped it back to basics so as not to cloud the issue...but I can see it's caused probs!)

Next....I think you've nailed the issue (my head was fogged last night after realising my program wasn't counting the revs right!)...essentially, my program traps the switch being closed (sort of!), but not the corresponding open. Therefore in reality, my program could see the switch being closed, head off to do some stuff elsewhere in the program, come back to check the switch & by bad luck/timing the next magnet could be passing so it thinks the same (original) magnet is closing the switch. therefore I need to wait for the switch to close, then open, then have my program act.

Joe... re the counter/variable melarkey - remember, I'm very new to this. I've almost certainly done a tutorial somewhwere & simply applied what I learnt there to my program! (I haven't a lot of time to dedicate to being a slick programmer, so I just throw into the program the little bit that I know!). Could you be so kind as to outline the tighter code for that little increment you've honed in on as being a bit 'first lesson at PICBASIC evening class'!). BTW ...I use this magnet/switch 'count' to derive when to send a pulse to a stepper. This stepper I'm sending the pulse to, moves in synchronicity with the main motor, back & forward (the idea being to neatly feed coppoer wire on to the main turning motor). It's really cool on the odd (seemingly fluke) times I've had it working!

Shane... the magnets are actually glued around the circumference of a wooden ring (& this ring itself is glued to the fan blades!). The diameter of this ring is about 10cm (4" if you're still in imperial) which makes for a circumference of 31cm ...the magnets themselves are about 1cm wide & there are 10 of them. So the magnets take up a third of the circumference - meaning a duty cycle of 33%?

Therefore, at a maximum of 350RPM, the magnets will pass by the switch at about 58 times per second. This works out at every 17ms....because of the magnet width, this yields a duty cycle of 33% - therefore the switch will actually be closed for about 5.6ms, every 17ms

Now my head still spins at the thought of building in the debounce aspect, so
with these 'knowns' I have, which would be the best approach to ensure an accurate switch 'closing' count?


(BTW, I'm thinking now that maybe an optical pickup would be a much better solution, as this removes the debounce aspect & I can have more resolution -I will look into this, but for now I'd really like to get the cheap 'n dirty solution working!)

ShaneMichael
- 28th April 2009, 16:41
Building a debounce isn't too hard, if it's even needed. It just depends on the magnetic switch you are using, if it's solid state you won't need to do much more than check if it's closed, being the way I am, I'd double check it again before actually stepping the moter etc. If it's a mechanical relay, that will need a "real" debounce and maybe some additional external hardware, like a cap.

To debounce you need a loop that checks if the switch is closed. If it is then increase a debounce var. and check it again, if it's not closed set your debounce var = 0 and keep checking. Determine the amount of time / number if times you want to increase your debounce var. you can put a pauseus 100 and recheck if it's still closed, and when your debounce var = 10 then you know the switch has been closed for at least 1 ms ( 100 us * 10 = 1ms)

Joe S. had the idea of using count, I've used it and it's simple.


count porta.1, 150 , freqval

The above code counts the pulses on porta.1 over 150 ms and stores the value in the Var "freqval".

In your case you would count for 10 ms? something like this:


Counting_Mags:
count portx.x, 10, mag_count ' count port x pin x for 100 ms
Num_Mags = Num_Mags + mag_count

if Num_Mags > 9 then One_Rev ' counted at least ten magnets so one revolution has occured, so step motor.

goto Counting_Mags

One_Rev:
Num_Mags =0 ' reset count
'do the rest of you stuff here

Goto Counting_Mags ' go back and count another revolution

Joe S. may have a better idea, and better code for you, above is where I would start, I'm no pro at this myself. I'd use the above code as an example, I just typed it out, so it still needs more work.

Archangel
- 28th April 2009, 17:05
Joe... re the counter/variable melarkey - remember, I'm very new to this. I've almost certainly done a tutorial somewhwere & simply applied what I learnt there to my program! (I haven't a lot of time to dedicate to being a<b> slick programmer</b>, so I just throw into the program the little bit that I know!). Could you be so kind as to outline the tighter code for that little increment you've honed in on as being a bit 'first lesson at PICBASIC evening class'!). BTW ...I use this magnet/switch 'count' to derive when to send a pulse to a stepper. This stepper I'm sending the pulse to, moves in synchronicity with the main motor, back & forward (the idea being to neatly feed coppoer wire on to the main turning motor). It's really cool on the odd (seemingly fluke) times I've had it working!

<b>HA HA HA, ME EITHER !</b> I wrote a Tachometer program, using count, look it over as an exemplar of using count. The code is in post #9. http://www.picbasic.co.uk/forum/showthread.php?t=9037



Now my head still spins at the thought of building in the debounce aspect, so
with these 'knowns' I have, which would be the best approach to ensure an accurate switch 'closing' count?


(BTW, I'm thinking now that maybe an optical pickup would be a much better solution, as this removes the debounce aspect & I can have more resolution -I will look into this, but for now I'd really like to get the cheap 'n dirty solution working!) Optical can be cheap and reliable, magnetic is good too, thinking hall effect switch. Do you really need 36 degree resolution (10 magnets)? Using an interrupt might be your solution to all this. I do not think I would use a magneto mechanical (reed) switch as a pickup, but using a hall effect would free you of all that debounce nonsense. Sam used my code with 1 magnet for his Tach. and says it works well. As for optical, tear open an old mouse and you will find a PIC and 2 optical pickups using shutter wheels. People use printed encoders for tabletop robots all the time. A coil of wire, magnets, and a comparator input will work too, that is what works most auto ignitions, in fact I used an old car distributor while working out my tach. code. A 555 timer can be used as a wave shaper if you are not ready to try comparators yet.

Bruce
- 28th April 2009, 17:57
Joes' idea for the hall effect sensor would be the way to go. Then you could simplify the
whole thing with a timer configured to count external pulses. Preload the timer to over
flow after 500 ticks, and have an interrupt flip the port pin to kill the motor.

The timer counts in the background, so you can have all sorts of other things happening,
code wise in the meantime. And with zero code for counting pulses.

If you prefer to sit & spin in a loop until killing the motor, you could just monitor the timer
overflow bit, and not use any interrupts.

HankMcSpank
- 28th April 2009, 18:59
Alas, my existing switch setup is a simple reed switch (so I have to debounce).

I've done some googling today & think that optical is the way to go. I'll probably use this guys implementation - a CD with some black stripes drawn on it!

http://www.vk2zay.net/article/29

http://www.vk2zay.net/article/28

(but perhaps having it feed into a monostable to clean those pulses up a bit)

Firstly, it appeals to the cheapskate in me, but more importantly, I can get even finer resolution - surprisingly 36 degree resolution isn't really sufficient...I'd much rather have 10 degrees or less

Totally off topic, but here's the maths.

Let's I'm feeding 0.15mm wire onto the main motor (actually the main motor holds a steel rod in jaws, upon which the copper wire feeds onto forming a coil)

So, for every turn of the main motor, I need the stepper motor (feeding the wire onto it), to traverse by 0.15mm.

My stepper is a 7.5 deg motor (meaning it takes 48 pulses to get it to turn one full revolution). I've placed some M8 threaded rod over the stepper shaft (this has a pitch of 1.5mm)....it is via this thread that I wrap the copper wire around feeding onto the main motor, if you can't visualize this...have a look here for a similar setup http://www.youtube.com/watch?v=Q_Cd_5zTt9w about 23 seconds in...he's using *much* chunkier wire, mine is more akin to thick hair).

Therefore for every full turn of the stepper (48 pulses) the wire moves 1.5mm (this being the thread pitch). But I *need* it to move just 0.15mm for every turn of the main motor. So to get the stepper to move the wire just 0.15mm, I need to send 4.8 pulses to the stepper for every turn of the main motor - obviously, I can't send 0.8 of a pulse to the stepper! Therefore if I had more tach resolution, I'd avoid such 'rounding' errors (or as I'm doing now, having to add in extra pulses every so often to make up for the shortfall)

Archangel
- 29th April 2009, 04:20
Hi Hank,
48 steps per rev, wow most steppers are 200 steps per rev. Saw the video. 1 Q & D way to get resolution in accurate form, Order from your local speed shop a degree wheel for setting cam timing, has 360 degrees embossed on an 8 inch aluminum disc. you can drill holes at exact spacing or use it as a protractor to make other discs.

HankMcSpank
- 29th April 2009, 13:07
Hi Joe,

Thanks for the top tip re the disc (I'll ponder that one!)

Re my program....well I got it working last night, here's what I did...

(Note as you read below, you need to know the incoming magnetoic switch is connected to PORTB.7 & the default condition is High...when the switch is closed it goes low)

Main:
If portb.7 = 0 then 'if low, then a magnet's leading edge has just past the switch
mag_start = 1 ' therefore set a variable condition to reflect this
Pause 3 ' pause a little to ensure we don't check the switch while it's bouncing
goto next1 ' if we have the mag leading edge, go to the next bit
endif
goto main ' keep looping until we do get a leading edge

next1:
If portb.7 = 1 then ''if high, then a magnet's trailing edge has just past the switch
mag_end = 1 ' therefore set a variable condition to reflect this
endif
If mag_start = 1 and mag_end = 1 then ' if both conditions are met, then we've just had one magnet pass
Goto one_magnet_passed
endif

one_magnet_passed:
mag_start = 0 'reset this puppy, ready for next time
mag_end = 0 ' ditto
Num_Mags = Num_Mags + 1 ' count number of magnets that have passed
if Num_Mags > 9 then one_rev ' counted at least ten magnets so one revolution has occured, so go do 'stuff'

one_rev:
Num_Mags = 0
pulsout PortC.0, 10 ; pulse the stepper

blah, blah.

The benefit of doing it in the above manner (I'm sure there are better ways, but hey...it works for me!), is that it'll work at virtual 'stop' speed, right on up to about 400RPM.

I went all low tech & taped a lump to the edge of the motor, so I could feel/count revs with my finger as the lump passed. I also used debug to put the rev count onscreen to make sure it concurred with my manual count - it was bang on.


Many thanks for all your help!



PS Joe, yes, 7.5deg steppers are somewhat unusual, it was a 'form feed' motor taken out of an old dot matrix printer...it's actually ideal for this job...I doubt I'll ever need more than 48 steps resolution per RPM for the wire types I'm winding. It's also a very light motor, therefore draws little power & is virtually silent. If I get a moment I'll post up a youtube video of what my setup is (warning - it's very kludgy. & lo-tech & ugly...but it does the job!)

HankMcSpank
- 16th May 2009, 15:04
Hi - me again!

Ok, I think I mentioned that I was going to bin my 'magnets & reed switch'...in favour of an optical pickup (I needed more 'resolution' & less debouncing) - well, I have all the pieces in place now...so why am I back?

well, I need help wrt how I can be sure to ascertain that my circuit (& program) is actually picking up all the pulses fine. And with a motor turning at between 300 & 400RPM, and 48 stripes per revolution...I lose count when doing this manually! :D

Here's the circuit I've implemented.... http://hans-w.com/RPM.gif (I should point out that Im not using the same PIC - I'm using a 16F690 - nor his hex code...as I need to be able to customize the program)

Re the tach pickup itself - on the edge of my turning motor is a phototransistor aimed at a round disc with 48 lines on it (essentially a pie chart knocked up in Excel, printed onto a CD label & then onto an old CD!!) ...as each one of these lines passes the phototransistor, a pulse ultimately appears at a PIC input pin.

It seems to be working reasonably well *but* I have a sneaking suspiscion, that either the electronics is not setup right (there's a preset in that schematic that needs setting optimally - I have a scope, but at 48 pulses per rev running at 400RPM, the trace is too jittery to set the levels in this manner).

What I'd like to know, is the best way to establish that *all* 48 stripes are being 'seen' by the PIC and everyrevolution (not just for one revolution, but say over 400 revolutions).

I'm figuring it'll need some form of counter, with the methodology being something along these lines (this is a labourious method!)....

Start counter
Pulse 1 arrives - output this info to screen along with counter time (I'm using the Pickit2 Uart tool to debug)
Pulse 2 arrives - output this data to screen along with counter time.

I can then cut/paste the above into Excel, do a bit of simple maths (ie subtract each 'counter time' from the previous, which will yield the time taken beteween successive pulses) & ultimately put this into a bar chart. All being well my bar chart should have bars of equal height from left to right.

Since the above method seems a bit long winded, I'm sure there must me a slicker way in real time, for example...

Start counter
Pulse 1 arrives - note the time in variable1
pulse 2 arrives - note the time in variable2
Subtract variable 1 from variable 2 (to give the time between pulses) - place into variable 3

then continue in a similar vein?

The clever bit would be to have a calculation that goes along the lines of "If the time between successive pulses is greater than say 90%, then we must have missed a pulse - output this info to screen via the Pickit Uart tool.

Does this sound plausible?

Could anyone help me out with a little bit of code to get me started please?(I've never dealt with counters previously!)

HankMcSpank
- 20th May 2009, 01:38
Ok...first sign of madness is talking to yourself - I must be totally barking. :)

Tonight, I knocked up an encoder wheel & used DT's interupt utility to assist the PIC in cleanly counting the 96 black stripes ...using interupts vs polling is a great success (ie I reckon all the black lines are being counted now).

But I've a new problem! :(

Previously, I have been using the Microchip Uart tool to output the number of encoder revs counted by the PIC onto my PC screen (essentially I just output a dedicated variable that increments after every 96 black stripes have been counted).

Up until now, everything was fine - could see my info onscreen quite fine.

My problem now is that becuase the black stripe interupts are running every 2ms (this number being based on a speed of 300RPM - which equates to 5 revs per second... therefore 200ms divided by 96 'black stripes' = 2.08ms between interupts) ...my onscreen info has become truncated/garbled. If I slow the wheel speed right down to say about 30RPM...it's fine....I can read my revs on my PC screen again.

this suggests that the interupts are interfering with the serial comms/Debug/Uart signal flow. (this is a little puzzling as I had thought the whole point of interupts was to be non disruptive in the sense they tuck everything away before heading off to do the interupt routine, & then pick up where they left off by 'restoring things as they were' after the routine?)

Does anyone have a cunning plan to allow me to get my simple onscreen Debug info back - I only need to see one small bit of info...this being the total rev count in pseudo real time onscreen. (I'm happy to consider alternatives too?!)

Jumper
- 20th May 2009, 02:03
Hi,

If you have a look at RB7 it is also called TX. This is the HARDWARE port for the serial communication. HSEROUT or HSEROUT2 will be the tool for this :-)

When you use the hardware serial port you only need to put a byte in the transmit buffer and then the PIC will send out the 10 bits for you with proper timing (start bit, 8 data, stop bit) so the interupts will not trash your data.

/me

HankMcSpank
- 20th May 2009, 13:45
Thanks for your input.

I'm struggling a little with the options available to get variable 'contents' to the outside world! Here's my understanding (though could be worng!)...

1. Hardware serial .... the traditional manner (neds a converter such as a MAX232). I'd like to keep it simple & component count low as possible, so I'm not pursuing this route.

2, PICKit2 - Uart tool....this is what I'm using at the moment, but like I say,the high number of interupts is causing havoc with the data I'm seeing onscreen..

Now this is where it gets a little 'grey' for me ....I'm using the command "Debug" to get my variable contents out and onto my PC via the Pickit2 Uart tool... I'm not calling any special .bas files - it just works! Is this using software or hardware?

Now then, I'm just reading on this page...

http://www.electro-tech-online.com/micro-controllers/39174-pickit-2-usart-example.html

where the guy declares in one of his headers...

Device = 18F4550
Clock = 8
Config FOSC = INTOSCIO_EC

// import usart module...
Include "usart.bas"

I'm figuring that going this route might actually use the PIC uart hardware? If so, this sounds ideal....can anyone shed any light here please?

Jumper
- 20th May 2009, 14:03
Some of the new 18-series PIC has the possibility to invert the hardware usart using a register setting. Your pic does not have that option..

just remember that sometimes people take component count and simplicity too far and they end up complicated and miserable. Sometimes a MAX can help... especially if you find one that requires zero external components :-)

HankMcSpank
- 20th May 2009, 15:34
Thanks once again.

I have to hold my hand up & say I'm getting a little forgetful nowadays....

it's been a bit of a long journey & during the many twists & turns, I'd forgot that a few weeks ago, I was actually using the HSEROUT command, with my PIckit2 programmer as the 'glue' between my PIC & my PC (http://www.picbasic.co.uk/forum/showthread.php?p=73184 ...though in that thread, you'll see for that particular 'moment in time' I aborted the HSEROUT route in favour of using DEBUG...but I can't use DEBUG anymore due to the high number of interrrupts my program is having to handle - also, I never did get to the bottom of why the command hserout ["Hello World", 10,13] only line feeds intemittently!

This HSEROUT/Pickiit2 method obviously does use hardware to get data out of the PIC (as opposed to the software based DEBUG command method), so I'm hoping that revisiting that aspect tonight will yield good results with the heavy amount of encoder wheel black stripe interupts!

ShaneMichael
- 21st May 2009, 00:28
I had the same trouble when I used "Debug" and interupts, using the HSEROUT worked great. You can read about it in a thread I had
"DT Interrupt and Elapsed Time Running Slow"

http://www.picbasic.co.uk/forum/showthread.php?t=11056

hope that helps,

Shane

HankMcSpank
- 21st May 2009, 11:39
Hi Shane...thanks for the info.

Just to report that my PC onscreen text from my PIC is no longer garbled with (heaps) of interupts ...using the HSEROUT command (9600 baud) coupled with the PICKit2 Uart tool - not a MAX232 chip in sight :-)

The last thing I now need to achieve is user input!

Essentially, when my program first starts, I need to prompt the user for input (using the HSERIN or SERIN command)- the input will always be three characters long - terminated with a CR.

I've googled a fair bit on this one (HSERIN & SERIN), but surprisingly, I've not find anything that a newbie like myself can latch onto easily!

Could anyone be so kind to help out?

Jumper
- 21st May 2009, 13:30
Just because the lid is on doesn't mean that the box is emplty.. there might not be a max232 chip, but something similar is inside the pickit2 providing the same function..

HankMcSpank
- 21st May 2009, 14:42
Just because the lid is on doesn't mean that the box is emplty.. there might not be a max232 chip, but something similar is inside the pickit2 providing the same function..

I realise that.

The thrust of my joy being, that as a newbie who has already outlayed for a Pickit2 starter kit...that I can actually use that to 'glue' my PIC to my PC (h/w serial comms wise)...ie I don't have to buy extra IC hardware, veroboard etc! (nor have my time sumped having to figure out how to connect it all together - I have enough on my plate as it is with PICs!)

How can I convert my three character string (which will always be numbers) into an actual number that my program can use - I guess what i need is a way of converting a string into a number? (or perhaps a way of taking the input as raw number vs the string method I'm using?)

My input doesn't work as a number wrt my program, as when I run it my counter starts at a different number to what I input (if for example I input 0032, the count below starts decrementing at 48, in fact it starts at 48 no matter what number I input!!)[/I]

Here's what I'm doing .....

turns_required VAR BYTE[3]
counter var byte
counter = 0
pause 800
HSEROUT [13,10]
HSEROUT ["Enter Number of turns required (with a leading 0)>>>", 13,10]

Main
HSERIN 5000,finish,[WAIT("0"),STR turns_required \3]
HSEROUT ["Number of turns will be.... ", STR turns_required \3,13,10]

counter = turns_required ' this is the key bit that isn't working as turns_required is a string

count_loop:
counter = counter -1
HSEROUT [DEC COUNTER,13,10]
pause 200
GOTO count_loop

HankMcSpank
- 21st May 2009, 18:09
Oops, that last posting of mine missed a middle bit out! It should have read more like below...


I've kludged the following code taken from here & there (plagiarism is alive & well!), towards getting the HSERIN working to fit my needs.


I'm using HSERIN to take 3 characters (which always will be numbers), input from my PC keyboard into my PIC. I'd then like to use these three separate numbers & combine them into a variable. All my serial end to end connectivity is is now working (no gobbledegook etc)...I'm happy with the signal flow aspect, fuses etc - ddata is moving to & fro fine - my query is now a basic simple programming one!

With HSERIN, I'd read that's it's best to have a 'trigger' character, followed on immdeiately by the actual data. So this is what I've done, when my PIC sees a leading 0, it takes in the folloiwing three bytes as a string. I need my 3 byte input string to be 3 actual numbers that my PIC program can act upon.


Here's what I'm doing .....

turns_required VAR BYTE[3] ; this is the user input for how many turns of a motor
direction_change var byte[3] ; again, user input for when the motor should change direction.

turns_required VAR BYTE[3]
counter var byte
counter = 0
pause 800 ; let things settle
HSEROUT [13,10]
HSEROUT ["Enter Number of turns required (with a leading 0)>>>", 13,10]

Main
HSERIN 5000,finish,[WAIT("0"),STR turns_required \3] ; wait for 3 bytes following the character '0;
HSEROUT ["Number of turns will be.... ", STR turns_required \3,13,10] ' oyutput it to screen to confirm

counter = turns_required ' this is the key bit that isn't working as turns_required is a string

count_loop:
counter = counter -1
HSEROUT [DEC COUNTER,13,10]
pause 200
GOTO count_loop


How can I convert my three character 'input' string (which will always be numbers) into an actual number that my program can use - I guess what i need is a way of converting a string into a number? (or perhaps a way of taking the input as raw number vs the string method I'm using?)

When I run the program, I can see the counter starts decrementing from a different number to that what I input (if for example I input 0032, the count below starts decrementing at 48, in fact it starts at 48 no matter what number I input!!)

HankMcSpank
- 21st May 2009, 22:29
ok, I've kludged it...but there's *got* to be an easier way than this...


'set up some variables....

turns_required VAR BYTE[3] ; the main input
UNITS VAR BYTE ' will use this to extract units from above
TENS VAR BYTE ' will use this to extract tens from above
HUNDREDS VAR word ' ' will use this to extract hundreds from above
TURNS_INPUT VAR WORD ' this will be used for the final goal - a useable number!!

pause 200 ' let things settle down a bit

HSEROUT ["Enter Number of turns required (3 digits + leading 0)>>>", 13,10] 'prompt for input.

Main
HSERIN 5000,finish,[WAIT("0"),STR turns_required \3] 'read in a 3 character string preceded by a '0'
UNITS = turns_required(2) - 48 'extract the last character (units) & revert it down to a true decimal
TENS = (turns_required(1) - 48) * 10 'extract the middle character (tens) & revert it down to a true decimal
HUNDREDS = (turns_required(0) - 48) * 100 ''extract the first character (tens) & revert it down to a true decimal

TURNS_INPUT = UNITS + TENS + HUNDREDS ' add them all together.


Using the above, I've turned my keyed in '3 character ASCII code' based string into its numeric equivalent, (that I can use later in the PIC program) ...but like I say, there's got to be an easier way?

ShaneMichael
- 23rd May 2009, 05:57
Instead of reading the HSERIN as STRING, read it as a DEC in to your WORD variable. Also you can use an interupt to know when you have data. If you got the interupt to work on your counter, you are close to getting it to work on data input. Darell Taylor interupts make it pretty easy. What you need is something like this at the begining:



INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
INCLUDE "Elapsed_INT-18.bas" ; Elapsed Timer Routines

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
INT_Handler TMR0_INT, _ToggleLED1, PBP, yes
INT_Handler RX_INT, _Check_Command, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T0CON = %10001000
@ INT_ENABLE TMR1_INT
@ INT_ENABLE TMR0_INT
@ INT_ENABLE RX_INT

When the Pic recieves data it will set the RX_INT flag and jump to the _Check_Command Sub, the pic will save a some data in the UART, so you don't need to be waiting for the data to come, just need to get it when it does. The Check_Command sub looks like this:


Check_Command:

hserin 10,No_Cmd,[Dec In_Val]


'************************************************* ******
'Cool code goes here, I was reading single digit numbers and had
'if statements to reply with different information, FYI calling another sub
'in an interupt sub was breaking the code. So be carefull jumping out
'and expecting things to work as normal on return.
'************************************************* *******
@ INT_RETURN
'******************************************
'Shouldn't make it to No_Cmd, since there was data on RX to get into
'this sub. The Int_Return above should jump you back to your code
'after you get your command
'******************************************

No_Cmd:
HSEROUT [10,"Made it to No_Cmd: I'm broke",10]

'***************************
'Don't know if disabling the RX_INT and enabling is needed
'I was trying to fix the issue of calling a sub from an interupt sub
'and thought this might help.
'***************************

@ INT_DISABLE RX_INT
@ INT_ENABLE RX_INT

@ INT_RETURN

I have seen examples of reading strings if data on a single HSERIN command, I haven't ventured that far myself, but you should find examples if you search this forum, I'm sure that's where I saw it.

Just to summerize, I used this to read single numbers 1-9 and had if statements for the code to react to, I didn't do math, so I might just be lucky that it worked.

Have Fun
Shane

HankMcSpank
- 24th May 2009, 01:19
Instead of reading the HSERIN as STRING, read it as a DEC in to your WORD variable. Also you can use an interupt to know when you have data. If you got the interupt to work on your counter, you are close to getting it to work on data input. Darell Taylor interupts make it pretty easy. What you need is something like this at the begining:

Shane

Hi Shane,

Thanks for the reply.

So all I need to do (sorry for the overly noob line of questioning), is instead of...

turns_required VAR BYTE[3]
HSERIN 5000,finish,[WAIT("0"),STR turns_required \3]

I could just do this

turns_required VAR WORD[2] '(which gives me 4 bytes? ...I actually only need 3 bytes), then this ? .....
hserin 10,No_Cmd,[Dec turns_required\3]

I've bolded the bits I'm uncertain about. Presumably the DEC part means the PIC reads the HSERIN info as Decimal (as opposed to a string). But what about where it places the 3 bytes? (I declared 2 words)...how do I pull the individual bytes out again?


Re the interupts...I actually used DT's interrupt routines to get my PIC counting some 'black stripes triggering a phototransistor' - superb results. As it goes, I don't actually need interupts for my HSERIN, as the PIC will only be asking for user input at the very beginning of its program.

I would however like a more graceful way of having to enter the data in rather than using a preceding 'trigger' character (in my case a '0'), as per this line though....

HSERIN 5000,finish,[WAIT("0"),STR turns_required \3][/I]

ie I'd like my program to start running, then a user just inputs data when prompted & without having to key that extra 0 at the front - it's really a bit cack having to do that!

ShaneMichael
- 24th May 2009, 03:21
Try it withouth making an array :

turns_required VAR WORD

a BYTE = 8 bits = 0 to 255
a WORD = 16 bits = 0 to 65535

so my understaning is that turns_required would hold a value up to 65535 without issue.

You can do some testing by reading the value in as a DEC with HSERIN and "echo" it back with HSEROUT as a DEC or read the value and blink an LED = to the number you entered. I wouldn't test that at 65535 LED blinks. If you do use an array "turns_required VAR WORD[2]" then you would save and retrieve data from turns_required[1] and turns_required[2]. I don't think you need to do that...

Hope this helps, Good Luck.
Shane