View Full Version : PIC based DRO
BillTodd 08-11-2008, 03:42 PM Continued from Welcome thread (http://www.cnczone.com/forums/showthread.php?p=487486#post487486)
Look like you haave been busy. The engraver looks great.
Thanks :)
I would be interested in how you used the PICs for your DRO`s. Did you design them yourself?
I wonder if they could work using encoders ?
Mario
The DRO (still work in progress) uses one 12F675 per channel to read the digital scale. The outputs of four PIC are multiplexed into one serial port of a PC. The PC runs a VB5 application that displays the readings (see attached).
The layout of the main form is designed to match my homebrew PC's touchswitches that are arranged down the left and right sides of the display
I spent sometime getting every thing to talk to each other neatly, so for instance, you can plug an extra vernier/scale into the adapter block and it just pops up on the screen.
As to using the PICs with quadrature encoder, I'm sure the little 8 pinners I've used lack the necessary hardware (you'd need a couple of fast counters to ensure no pulses were lost). The ones to use would be the dsPIC devices like the 30F4012 (?) which have the quadrature hardware inside.
mc_n_g 08-12-2008, 05:00 PM Could you post more metails on the project. I have been playing in various pics of the past year and would like to get a little more advanced in reading other pulses.
BillTodd 08-14-2008, 07:14 AM Could you post more metails on the project. I have been playing in various pics of the past year and would like to get a little more advanced in reading other pulses.
What pulses are you trying to read?
mc_n_g 08-14-2008, 03:01 PM I am trying to do a better job in understanding teh analog and digital side of the processing. I have played with temp sensors and other simple items for input. I have not worked with any encoders at all. This is where I am lacking examples and expereience.
BillTodd 08-14-2008, 04:57 PM I'm not actually reading encoders. I'm decoding the digital data outputs of those cheap Chinese digital calipers (see :examples here (http://www.yadro.de/digital-scale/protocol.html)). To keep my circuit simple, I'm using the PICs onboard comparitor and reference to convert the low level (~1.5v) signal to one that the PIC can read.
This circuit is of a single device reader powered by the serial port.
http://homepage.ntlworld.com/bill_todd/scale/_wp_generated/pp2a5acee8.png
The LEDs (D1,2,3) limit the voltage to about 1.2v when the PIC drives the scale's inputs.
Marzan 08-20-2008, 09:44 AM As to using the PICs with quadrature encoder, I'm sure the little 8 pinners I've used lack the necessary hardware (you'd need a couple of fast counters to ensure no pulses were lost). The ones to use would be the dsPIC devices like the 30F4012 (?) which have the quadrature hardware inside.[/QUOTE]
Hi Bill. It all looks impressive. You have certainly done a good job. I wish I had your talents. Unfortunately I am just a Trial and error learner at both electronics and Cnc`ing If i had one wish it would be that there was a way to verify my steppers with an encoder in Mach 3. A task too difficult for me with my limited experience.
Marz
BillTodd 08-20-2008, 10:22 AM If i had one wish it would be that there was a way to verify my steppers with an encoder
The usual method is to mark the motor's starting position accurately, then run a torture test (i.e. a test that runs the motor at various speeds back and forth until finally return ing to the start point), then check the motor has returned to the start postition correctly.
Marzan 08-20-2008, 10:58 AM The usual method is to mark the motor's starting position accurately, then run a torture test (i.e. a test that runs the motor at various speeds back and forth until finally return ing to the start point), then check the motor has returned to the start postition correctly.
Yer Bill. I have done all that. I set up a dial indicator on both axis and then ran a g code program with rapid moves for a 1/2 hr. I tuned the motors for 10% under the max revs before it misses pulses. Its just sometimes if I push the toolbit too hard it misses a few steps. I know thats my fault, but it would be nice if it could correct itself. If only I had the money to run servos....
Marz
BillTodd 08-20-2008, 03:59 PM but it would be nice if it could correct itself.
I see. Can mach3 do that, if it has encoder/count inputs?
What sort of input does Mach3 need?
Marzan 08-21-2008, 09:34 AM I see. Can mach3 do that, if it has encoder/count inputs?
What sort of input does Mach3 need?
I`m not really sure.I was thinking along the lines of another pic or such countin pulses and comparing the result with an encoder (sort of like a virtual closed loop system) and if it misses steps using one of the inputs to signal a positioning error
Marz
Robin Hewitt 08-21-2008, 12:03 PM I'm brewing up much the same but with a home made computer board reading scales and stepping motors.
The step timer interrupt compares "where I am" with "where I want to be" and steps accordingly.
The "where I am" can change at any moment should a report be received from any of the 3 scale interrupts. (I read them with hardware because any lag will only serve to confuse it).
At the end of an x,y,z stepping sequence it works out the error on all 3 axes. Should any be outside tolerance it doesn't update the "where I want to be" to a new position. This means I get remedial steps to put it back on course.
Questions are, wil it do more remedial steps than moving steps, and, how tight can I put the tolerance :D
I only have to mount the scales and I can find out :rolleyes:
BillTodd 08-21-2008, 02:37 PM I'm brewing up much the same but with a home made computer board reading scales and stepping motors.
The step timer interrupt compares "where I am" with "where I want to be" and steps accordingly.
The "where I am" can change at any moment should a report be received from any of the 3 scale interrupts. (I read them with hardware because any lag will only serve to confuse it).
At the end of an x,y,z stepping sequence it works out the error on all 3 axes. Should any be outside tolerance it doesn't update the "where I want to be" to a new position. This means I get remedial steps to put it back on course.
Questions are, wil it do more remedial steps than moving steps, and, how tight can I put the tolerance :D
I only have to mount the scales and I can find out :rolleyes:
Interesting idea :) Although,the missed steps may not be able to be corrected until the cause has been removed.
i.e. if it drops steps because of excess speed v load, will there be time to correct them before the next motion without increasing the frequency of the pulses thus exacerbating the speed v load problem?
(Well worth trying though :))
Robin Hewitt 08-21-2008, 04:10 PM The fast traverse is a completely separate interrupt handler, precise placement only happens at speeds where the motors can handle an instantaneous reversal.
There is more work to do. When it encounters back lash it will tend to trail by the tolerance and I will need extra remedial steps. OTOH I'm not going to try to fix anything until it has had a chance to tell me what needs fixing.
I'm writing the code and everything runs in SRAM. I can recompile and upload all new in a matter of seconds. I am in control :D
Marzan 08-21-2008, 06:50 PM Hi Robin. What a brilliant idea. When you get it right you will have solved one of the major issues with using steppers. i would be interested in the outcome.I had another thought that if i had the knowhow would be worth pursuing. What if you had a PIC counting pulses sent my Mach 3 and then the PIC moved the stepper motor using the encoder to go to the correct position? Its probably complicated, and you would get some lag,but i would gladly put up with lag for accuracy.
BillTodd 08-26-2008, 01:02 PM What if you had a PIC counting pulses sent my Mach 3 and then the PIC moved the stepper motor using the encoder to go to the correct position?
Hmmm , That wouldn't be too difficult.
I use a PIC (16F84 and an L6219) to drive the Z motor on my engraver, it'll happily keep up with the step inputs from the controller using interrupts. It even has has a couple of unused timer/counters that could be used to track an encoder. Might be worth a look
[I still wonder, if you're going to add all this complexity you might be better of using proper servo-motors]
Marzan 08-26-2008, 10:12 PM Hmmm , That wouldn't be too difficult.
[I still wonder, if you're going to add all this complexity you might be better of using proper servo-motors]
Yeah. you could be right, but steppers and encoders on ebay are a lot cheaper than servos, and if a cheap PIC could be made to act as a Pseudo closed loop it would be just as good for a lot less money for the DIYers
BillTodd 08-27-2008, 06:28 AM Yeah. you could be right, but steppers and encoders on ebay are a lot cheaper than servos, and if a cheap PIC could be made to act as a Pseudo closed loop it would be just as good for a lot less money for the Dyer's
"just as good.." No, I'm afraid not.
If a servo system requires speed to catch-up with the commanded steps all it has to do is dump more power into the servo motor (right up to the point it/something goes bang or hits a power limit) . A stepper motor driver cannot do this. The best a closed loop stepper system could do is to wait until the overload event has passed then add pulses to get back on track.
Now let's assume the above error occurred while cutting material with multiple passes ( caused by a knot in a piece of wood for example) ; both would have left a 'bump' of uncut material. The servo system would have probably left a smaller bump than the stepper (since it had more power available to attack the bump), so subsequent passes would likely reduce the bump. The stepper system would have to leave the bump untouched and add to the bump while it waited to correct the error. Subsequent passes are very likely to stall again at the initial bump and... well you can see where it's going.
Robin Hewitt 08-27-2008, 08:41 AM Now let's assume the above error occurred while cutting material with multiple passes ( caused by a knot in a piece of wood for example) ; both would have left a 'bump' of uncut material.
If you overload a stepper to the point where you lose steps everything thereafter is garbage. That's why us stepper people tend to drive them way below capacity. I have more than enough power to snap the tool but I try not to use it :D
With the scales attached, theoretically if it can't cut the material all 3 axes stop, possibly within 0.02 seconds depending on the tolerance. The repeating step pattern will cause it to back off and then try again and again until it succeeds, or not as the case may be.
BillTodd 08-27-2008, 12:28 PM With the scales attached, theoretically if it can't cut the material all 3 axes stop, possibly within 0.02 seconds depending on the tolerance. The repeating step pattern will cause it to back off and then try again and again until it succeeds, or not as the case may be.
That would be the advantage of taking control at an earlier stage in the system.
Although, If your steppers aren't losing steps (because you're driving them well within limits) why do you need the recovery system? :)
Robin Hewitt 08-27-2008, 01:02 PM Not so much a recovery system, more an external reference to locate the table without depending on everything staying in adjustment on a cheap mill :)
I have a certain amount of spring in the system. The Gibbs are tighter at the ends where I rarely stray making backlash a variable. Changing pressure from the tool makes it unpredictable.
Aiming to better 1 thou accuracy has become a sort of Grail quest... Not quite sure what I'd do with it if I found it but I feel compelled to try :D
Marzan 09-04-2008, 09:47 AM Hmm..I think i found another hole im my theory about using pics to link encoders to steppers.It would be feasible to control one stepper that way but I guess would be a problem when integrating X,Y, and Z when interpolated on a g2 for example. If one took a bit longer to correct a couple of missed steps, it would throw the whole move out of wack. I guess you could have some way of all 3 PICs knowing what each of the others is doing.
mrbasher 07-08-2009, 12:34 PM Bill,
I am having trouble simply reading the 90KHz clock single from the scales using just about every method I can think of, be it through a separate comparator, an opamp configured as a comparator, and even a combination of NPN and PNP transistors.
Can you give us a little insight into how you are using the comparators on the chip to accomplish this and as well a little description of why there are LEDs connected to the clock and data lines.
I've also read conflicting info on whether or not the signal from the scales is +1.5v high and 0 low, -1.5v high and 0 low or some combination of those. :) I have an oscilloscope being delivered today which should help ME see what's going on.
As of now, all I see is 3 "pulses" per second on the clock. However, using a homebrew soundcard oscilloscope technique I can definitely see that it's outputting the usual 2*24. Unfortunately the card doesn't record fast enough to see the clock, just the basic outline of it which looks like this _/-|-\_ (pardon the wonderful ascii rendition) hehe The -'s there are obviously the clocking which ends up somewhere between high and low because it can't resolve on the soundcard.
ok so I'm all ears. :D
Thanks!
Robin Hewitt 07-08-2009, 12:59 PM This was my circuit to convert scale volts to TTL. Screwed it to the back of the scale, putting new mounting holes on the PCB isolated the scale.
Resistor pair R7 and R8 are there to hold the scale within the range of the comparators. 100k was not enough, needs a cap. Had a nasty surprise when I found the scale frame was connected to + on the battery so I had to isolate the scale steel bar to :)
BillTodd 07-08-2009, 01:26 PM Hi Jon,
The scale's signal polarity is conventional i.e. positive = hi, complicated by the fact that the battery +ve terminal is connected to the body of the scale making the 'signal ground' actually -1.5v. I've compensated for this by making my PIC's Vss -1.5v and Vdd +3.5. Once this is done the PIC sees a 1.5v pulse into the comparator's inputs
The resistor and LED circuit is to simply limit the voltage to about 1v2 when the PIC is driving the CLK and DATA lines. The PIC drives the CLK and DATA lines hi to reset the scale and switch modes (e.g. from slow 300mS to fast 20mS update)
Reading the data from the scale is simply a matter of
a) setting the comparator to compare the CLK input with the internal Vref (set at about 0.75v)
b) wait for clock = hi (by testing the comparator's o/p)
c) wait for clock = lo
d) switch comparator input to DATA line
e) test comparator o/p (switch carry bit as necessary)
f) shift data into store
g) loop for 24 bits for binary scale incremental and again for absolute
Below is the assembly code (it's fairly well commented, so it shouldn't be too difficult to read):
Note: there are two types of scale data.
1)Binary 1/20480th of an inch (in two 24bit words one incremental from last zero, one absolute from power on [battery insert])
2)BCD - which has 6 4bit nibbles representing the display data plus 4bits mode info (Sign, 1/2 thou, mm/inch, not-used)
My code reads either type, by first counting the number of CLK pulses to determine the type of scale connected to the PIC, then jumping to the appropriate routine.
;(c) W.K.Todd 2005
;Read data bits from Vernier scale
;V2.00 - uses on-chip comparator for both inputs
;GP0 - data
;GP1 - clock
;------------------------------------------------------------------
;vernier data is 24bits (lsb first) absolute position
;followed by 24bits relative pos (as displayed)
;clock remains high for 50uS between data bursts
;each bit represents 20480th of an inch
;data is valid on falling edge of clock
;Clock is high for 50uS prior to first valid clock edge
;------------------------------------------------------------------
;4bit digit output from new verniers
;
;verniers tx data as 7 nibbles, first 6 nibbles are display digits lsd-msd,
;7th nibble is: Sign bit(1=-ve), Half thou bit(1=0.0005"), mm/inch bit(1=mm), always high bit
;Data is valid on falling edge of clock
;Clock is high for 50uS prior to first valid clock edge
;-------------------------------------------------------------------
;Vdata equ 0x00 ;4 bytes shift register
; ;Vdata = MSByte
; ;Vdata+1 = NSB
; ;Vdata+2 = nsb+1
; ;Vdata+3 = LSByte
;
;initialise comparator etc
;
VInit BSF status,RP0 ;select bank 1
movlw B'10100011' ;set Vref ~ 0.75v, Vdd = 5v;(24/5)* 0.75
movwf VRCON
BCF status,RP0 ;select bank 0
movlw B'00010110' ;multiplex in, int ref output inverted, output
movwf CMCON
return
;
;get vernier data into buffer
;
GetVD bcf CMCON,CIS ;switch comp to clk input
btfsc Mode,Vtype
goto GetVDD ;get vernier decimal data
call synlp ;gvd
call GetVDB ;get and discard ABS
GetVDB movlw 0x80 ;set hi bit of shift register
movwf Vdata
clrf Vdata+1 ;set-up for 24bits
clrf Vdata+2
clrf vdata+3
cphlp btfss CMCON,COUT ;wait for clock to go high
goto cphlp
bcf status,c ;clear carry ready
;wait clock low - grab bit
cpllp btfsc CMCON,COUT
goto cpllp
bsf CMCON,CIS ;switch comp to data input
btfsc CMCON,COUT ;test data bit
bsf status,c ;set carry if data = 1
rrf Vdata,f ;roll bit into msb buffer...
rrf Vdata+1,f ;then...
rrf Vdata+2,f ;into lsb.
bcf CMCON,CIS ;switch comp to clk input
btfss status,c ;exit when 24 bits shifted
goto cpllp
return
;sync - wait for clock low for >1mS
synlp btfsc CMCON,COUT
clrf Vdata+3 ;use Vdata+3 as temp timer
decfsz Vdata+3,f
goto synlp
return
;
;get decimal vernier data
;
GetVDD movlw Vdata+3
movwf FSR ;set indirection pointer
;set up nibble counter
clrf vdata+3
call synlp
movlw 0x08
call VDbyte ;first nibble 1
decf FSR,f ;Vdata+2
movlw 0x80
call VDbyte ;2&3
decf FSR,f ;Vdata+1
movlw 0x80
call VDbyte ;4&5
decf FSR,f ;Vdata
movlw 0x80 ;get last byte 6&flags
VDbyte ;get byte or nibble
movwf INDF
cphlp1 btfss CMCON,COUT ;wait for clock to go high
goto cphlp1
bcf status,c
cpllp1 btfsc CMCON,COUT
goto cpllp1
bsf CMCON,CIS ;switch comp to data input
btfsc CMCON,COUT ;test data bit
bsf status,c ;set carry if data = 1
rrf INDF,f ;roll bit into msb buffer...
bcf CMCON,CIS ;switch comp to clk input
btfss status,c ;exit when 8 bits shifted
goto cpllp1
return
;measure the vernier reading speed (300mS slow,20mS fast)
measure bcf CMCON,CIS ;switch comp to clk input
call synlp ;wait for clock low >1mS
bcf Mode,Fflg
;if clock occurs within ~25mS then Fast flag will be set
movlw 25
movwf vdata ;borrow vdata as counter
m2lp btfsc CMCON,COUT
bsf Mode,Fflg ;
decfsz vdata+3,f
goto m2lp
decfsz vdata,f
goto m2lp
return
;
;check vernier type by counting clock pulses
;
GetVT bcf CMCON,CIS ;switch comp to clk input
call synlp ;wait for clock low
clrf vdata+1 ;used as timer
movlw 30
movwf vdata+2 ;clock pulse counter
vthlp btfss CMCON,COUT ;wait for clock to go high
goto vthlp
cntlp btfsc CMCON,COUT ;wait for clock low
goto cntlp
decf vdata+2,f ;count bit
clrf vdata+1 ;used as timer
cnthp btfsc CMCON,COUT ;wait for clock high or timeout
goto cntlp ;if clock hi then wait for clock low
decfsz Vdata+1,f ;exit loop if low >~1mS
goto cnthp
bcf Mode,Vtype
btfss Vdata+2,7 ;test if >30 clock pulses
bsf Mode,Vtype ;if not then flag as new type vernier
return
mrbasher 07-08-2009, 04:49 PM Ok cool! Thank you both of you for the info. That's basically what I needed and I don't know how I overlooked the necessity of the LEDS for the using clock and data to set the mode and zero. :)
I do have another question though... Where did you source the -1.5v for ground? The scale's ground?
Sorry if this is obvious, I'm still learning and I gotta start somewhere :)
BillTodd 07-08-2009, 05:01 PM If you squint at my picture long enough ;) you should be able to make out a 5v regulator with a resistor + Red LED giving about 1v5 above the regulator's 0v, this is taken to the common ground so giving -1v5 (regulator 0v and PIC Vss) & +3v5 (reg +5v and PIC Vdd) from a floating PSU input.
Where did you source the -1.5v for ground? The scale's ground?
No, the scales ground (battery +ve) is the same as the PC's ground i.e. Earth potential, the -1v5 is the scale's power supply input (battery -ve).
mrbasher 07-08-2009, 05:22 PM If you squint at my picture long enough ;) you should be able to make out a 5v regulator with a resistor + Red LED giving about 1v5 above the regulator's 0v, this is taken to the common ground so giving -1v5 (regulator 0v and PIC Vss) & +3v5 (reg +5v and PIC Vdd) from a floating PSU input.
No, the scales ground (battery +ve) is the same as the PC's ground i.e. Earth potential, the -1v5 is the scale's power supply input (battery -ve).
Oh my... I appologize. I was too busy looking at the code and I didn't scroll down far enough to see the picture you attached. :D I was referencing the diagram on your site.
Almost time to go home so I can work on something fun. :)
mrbasher 07-10-2009, 02:10 AM Well after some extensive messing around it seems that I need to learn assembly... I've been programming these little chips for awhile now using MikroC and it's worked quite well until now. Unfortunately, it looks as though the code just doesn't run fast enough to pick up those 90khz signals unless it's done in assembly. Simply reading the value of COUT is taking serval intructions (when you look at the assembly version), which just isn't necessary.
No biggy :) Knowing assembly should make using the datasheets much simpler!
Be back soon!
BillTodd 07-10-2009, 06:20 AM Well after some extensive messing around it seems that I need to learn assembly
PIC assembler is easy only 35(?) instructions (it's the carry that always throws me - is it set or reset after subtraction???? - catches me out every time!)
I don't think HLLs like 'C' are ideal for programming these little controller chips. PICs in particular benefit greatly from careful optimisation even in when writing in assembler.
Is it possible to embed and call assembler routines in your version of C?
mrbasher 07-10-2009, 10:18 AM I can place assembly directly into the C code and have done that with some minor things... However, I'm not certain how to use them together in a looping or conditional situation.
BillTodd 07-10-2009, 11:08 AM If you want to just concentrate on the convert and display device, and are happy using async serial instead of I2C, I could let you have a copy of my obect code and a run down of the interface protocol? (may even have the board design somewhere)
mrbasher 07-12-2009, 11:33 AM If you want to just concentrate on the convert and display device, and are happy using async serial instead of I2C, I could let you have a copy of my obect code and a run down of the interface protocol? (may even have the board design somewhere)
Actually that would be really nice... I've been spending some time the last few days getting a grasp on programming the PIC's in assembly. It's really quite interesting. I probably won't use your code directly and as more of a guideline. Not because I think I could do it better, but because I still want to learn assembly for these chips. :)
If you have a larger picture of the scale schematic you posted that would help quite a bit.
Thanks again for all of your help.
BillTodd 07-12-2009, 01:32 PM I've been spending some time the last few days getting a grasp on programming the PIC's in assembly.
Like most things, you have to get your knowledge up to a 'critical mass' Once you can get the thing to compile you're pretty much there :) [these days I find the 'mass' evaporates faster and faster - I have to top-up every time I revisit it!]
won't use your code directly and as more of a guideline.
It might just confuse you :) (I learnt 'assembly' years ago programming Z80s with simple assemblers, so I don't use a fraction of the newer assembler/compiler's capabilities)
The source should open with MPLab 8 or later.
Keep us informed of your progress :)
mrbasher 07-12-2009, 08:55 PM Alright so I've made some pretty decent progress!
After going through the typical blinking LED, input, etc. stuff I finally decided to take a crack at reading this signal. To my surprise, my first try worked!
I decided my first step should be simply determining if the PIC was reading the signal correctly. This was done by turning a pin on when it sensed the clock was high and turning it off once the clock went back low. This turned out to be surprisingly simple and FAST... Here is the little bit that does that portion:
RL1 btfss CMCON,COUT ;wait for clock high
GOTO RL1
XORWF GPIO,5 ;toggle GP5
RL2 btfsc CMCON,COUT ;wait for clock low
GOTO RL2
XORWF GPIO,5 ;toggle GP5
GOTO RL1
I then connected one channel of my oscilloscope to GP5 on the PIC and one channel to the scales output (which was also going into the pic).
Check out the result in the attached image. :D The red line is the output from the PIC and the blue line is the output from the scale... They were both being read at the same time.
I would like to add that I could NOT get this to work correctly using MikroC... Nothing against it, but the speed difference is quite obvious.
mrbasher 07-12-2009, 09:07 PM One little change to that code... GPIO,5 should actually be GPIO,1 ;)
RL1 btfss CMCON,COUT ;wait for clock high
GOTO RL1
XORWF GPIO,1 ;toggle GP5
RL2 btfsc CMCON,COUT ;wait for clock low
GOTO RL2
XORWF GPIO,1 ;toggle GP5
GOTO RL1
BillTodd 07-13-2009, 06:20 AM You're a fast learner :)
Be aware there pitfalls if you talk to the GPIO using those infamous read-modify-write instructions sometimes you get away with it sometimes you don't (there's full explanation on the microchip site).
mrbasher 07-13-2009, 07:24 PM You know, I've been looking through your code and I've reached a bit of a dilema...
You've really done a fantastic job and from what I can tell, if I were to do it on my own... I'd just be reinventing the wheel and in the end, come up with basically the same thing. (there's only so many ways to do it...)
So, I think I am going to concentrate on part 2 of this which is the display/control end of things. The plan is to connect all of these to a single 16F883 which will manage the scales and display the info on a small LCD.
The 16F883 has hardware USART so, that part's done for me :D
Gonna do this in assembly so wish me luck. The LCD should prove interesting... It has a standard HD44780 controller.
BillTodd 07-14-2009, 08:26 AM The plan is to connect all of these to a single 16F883 which will manage the scales and display the info on a small LCD.
I was thinking of doing the same in order to replace the PC. Care to share?
The 16F883 has hardware USART so, that part's done for me
The DRO displays need to be updated as fast as possible (to make it feel right on the lathe/mill). This means using the scale's fast 20mS mode. With three (or four) axes to display this gives you 5-6mS to collect, parse, convert and display the binary/bcd to inches and/or millimetres.
Incidentally, I find the simultaneous display of Inch & mm very useful on the mill.
Gonna do this in assembly so wish me luck.
The binary/bcd inch/metric conversion maths may be easier in C.
The LCD should prove interesting... It has a standard HD44780 controller.
No that's easy :) (initialising the 44780 can be a pain). I have some four bit driver code if need it. However, I suggest you make your interface 8 bit, since it'll give you the option of using a VFD module (when you find the LCD unreadable ;))
Attached is a zip with a compiled version of the PIC code and the VB5 DRO application installer.
The app' has a sort of 'demo' mode, so you can look at it and play with out an interface. Either of my interfaces - single com-port powered or multi channel will work with it. One of these days, I'll finish of the MDI version.
I'll try to put together a typical interface protocol conversation for you later.
mrbasher 07-14-2009, 02:41 PM Awesome, thanks for the code. :) I'll have to play around with it when I get home this evening.
I agree on possibly just writing the program in C. I already know C well and there are built in routines for handling the LCD in either 4 or 8 bit mode. Given the chip's built in usart, the only real code is going to be handling the commands to and from the scales and the conversion of incoming data.
I suppose I can always practice my assembly on some future project :) Maybe I'll rewrite the software I used on my stepper driver boards using assembly... hmmm
As for sharing, of course... I'll share everything I have once things are completed. MikroC spits out an asm file as well, so that might be worth looking at by someone that knows whats what... Could most definately be improved. :)
I will keep you updated.
BillTodd 08-13-2009, 04:04 PM How's it going?
mrbasher 09-15-2009, 10:17 AM Sorry for not giving any updates or anything for so long. I'm still working on this little by little. It's been hard to find time lately as I just bought a house and am trying to finish getting settled in. :( Hasn't left much time for fun stuff.
KiloOne 02-01-2010, 08:34 PM Hello Bill,
What a great DRO project you have done.
I think I want to give this a try. I found this thread after I have bought a 18F87J50 demo board, this PIC has USB capabilities. Boy does that add complexity!
I only want a single DRO in my own VB program so I can just buy a $15 Serial to USB adapter and try your much simpler method.
I just built a hex file from your code using MPLAB IDE v8.01 and I ended up with a byte for byte copy of your hex file, that was cool.
I think I'll order some 12F675's tonight.
Would you care to share some VB code that reads the serial port and puts the scales value in a text box?
Thanks,
Dale
BillTodd 02-03-2010, 07:21 AM Hi Dale,
My program is a torturous mess of VB5 object code, so you probably wouldn't want to copy it :)
The PIC code responds to 2 byte commands with a VB friendly string (I think it is all documented in the source listings). The receiving app' has to asynchronously workout what it has received then act appropriately (sound hard than it is) . I'll dig out some code for you later.
Bill
BillTodd 02-03-2010, 09:26 AM Dale,
This is how it's done in my application ATM (I'll try to simplify it later)
Data received by the Comm control is passed to a Scale Control object in the form of a string.
Private Sub MSComm_OnComm()
Dim s As String
'Dim T As Single
Select Case MSComm.CommEvent
Case comEvReceive
s = MSComm.Input
SC.DataInput s 'pass data to scale control object
Case Is = comEvCTS
'CTS line change
If MSComm.CTSHolding Then
SendIdentify
Else
SC.RemoveAll 'lead unplugged
End If
End Select
End Sub
The Scale Control object splits up the string, works out what to do with the parts and passes that data onto the appropriate handler.
'* < DataInput Sub Header >
'* Author.......: {UserName}
'* Date.........: 03-Aug-2007 12:32
'* Purpose......: Data from verniers
'* Assumptions..:
'* Effects......:
'* Inputs.......: sting data from scales
'* Returns......:
'* ------------------------------------------------------------------------
Public Sub DataInput(vData As String)
Dim strErrmsg As String
If Not IsInIDE() Then On Error GoTo DataInputError
'------------------------------------------------------------------------ Main Code
'update appropriate vernier class
Dim VS As clsVernier 'Vernier scale object
Static RXS As String
Dim SCid As String
Dim sData As String
Dim vMode As Integer
Dim vType As String
Dim vUnit As String
RXS = RXS & vData
Do While InStr(RXS, ":") 'Len(RXS) >= 9
sData = Sfmt.SplitAtDelim(RXS, ":")
Select Case Left(sData, 1)
Case Is = "C"
'connect e.g CX
SCid = Mid(sData, 2, 1)
'AddScale ScID
RaiseEvent ScaleComms("I0")
Case Is = "D"
'disconnected e.g DX
SCid = Mid(sData, 2, 1)
RemoveScale SCid
Case Is = "I"
'info string ID,Mode,Type,Unit e.g. IX,0,Decimal,Inch:
SCid = Mid(Sfmt.SplitAtDelim(sData, ","), 2, 1)
vMode = Sfmt.SplitAtDelim(sData, ",")
vType = Sfmt.SplitAtDelim(sData, ",")
vUnit = sData
If Not Scales.Exists(SCid) Then AddScale SCid
For Each VS In Scales ' find the correct Vernier Scale object
If VS.Key = SCid Then
VS.Mode = vMode
VS.ScaleType = vType
VS.Unit = vUnit
End If
Next
Case Is = "R"
'scale has been zeRoed (can't use Z)
SCid = Mid(sData, 2, 1)
For Each VS In Scales
If VS.Key = SCid Then
VS.ResetAbsolute
End If
Next
Case Else
'data e.g. X+00.0000
SCid = Left(sData, 1) 'uses the the identifier e.g. W, X,Y or Z to choose the scale ID
If Scales.Exists(SCid) Then 'check if scale ID is in scales collection
Set VS = Scales.Item(SCid) ' set current vernier scale object
VS.Setdata Right(sData, Len(sData) - 1) ' pass data
End If
End Select
Loop
'------------------------------------------------------------------------ End of Main Code
The Vernier Scale object has to work out the data type convert it and save it in a standard form (e.g. inches)
The PIC can output three type depending the make of digital vernier used:
1)A 6 digit Hex number where 20480(d) units = one inch
2)A signed two significant digit + four decimal place string in Inches
3) A signed three significant digit + two dp string in millimetres.
Public Sub Setdata(sData As String)
'takes sData string e.g. H000000 (hex 1/20480"), +00.0000 (inches) or -000.00 (mm)
'and converts it to ABS value
Dim pos As Long
Dim NV As Single
Select Case True
Case Mid(sData, 5, 1) = "."
'decimal vernier in metric mode
NV = Val(Right(sData, 7)) / 25.4
Case Mid(sData, 4, 1) = "."
'decimal vernier in inch mode
NV = Val(Right(sData, 8)) ' convert decimal string
Case Left$(sData, 1) = "H"
' convert hex string
pos = 1 - Val("&" & sData & "00") 'shift 24bit to 32bit and invert
NV = pos / 5242880 '20480* 256
End Select
'add to glitch filter
If mRev Then
AddToFilter NV * -1
Else
AddToFilter NV
End If
mController.Refresh Me 'update the controller
End Sub
In order to improve the display stability and remove jitter and glitches I added a simple filter to the output.
Private Sub AddToFilter(NV As Single)
'filter new value add to abs value
Static FI As Integer 'filter index
Dim n As Integer
Dim FT As Integer
FT = UBound(Filter())
Dim Tot As Single
'glitch filter
'average last few readings
Filter(FI) = NV
FI = FI + 1
If FI >= FT Then FI = 0
For n = 0 To FT - 1
Tot = Tot + Filter(n)
Next
mvarAbsValueInch = Tot / FT
End Sub
The display routine reads the Scale object's AbsValueInch or AbsValueMM (the scale object does the conversion to a single precision variable).
KiloOne 02-03-2010, 06:17 PM Bill
Thanks, thats great, I'm sure I can make use if this.
I'm still considering using an 18F13K50 20 pin USB PIC but I did order the 12F675's.
I'm wading thru the Microchip USB dll, mpusbapi.dll. It might be not too bad and I can still adapt your VB code somewhat to do it.
I'm thinking of making a round PCB the size of a 2032 battery that is used in my calipers. One SOIP 18F13K50 and very few external components. It will have a vertical mini-USB connector that comes thru a hole in the battery lid. I can sneak the 2 signal wires inside the case to their pcb pads and solder them on thru the existing connector hole. Should be pretty neat, especially if I can use the USB PIC.
24 inch calipers for $80 and DRO to a PC, very appealing.
Dale
BillTodd 02-03-2010, 07:10 PM Be aware that the callipers have the battery +ve grounded (i.e. they sort of run a negative rail).
I was considering making an opto-isolated version to avoid the problem in future.
KiloOne 02-03-2010, 10:23 PM I don't think mine has a +ve Gnd.
When I check for continuity, with the battery out, between both battery contact points on the pcb and the metal of the caliper, they are both open.
BillTodd 02-04-2010, 04:49 AM That sounds like a very different (and better) type of calliper. The 2032 battery is a great improvement. What type of calliper is it? Are you sure that it outputs the same code as the cheaper Chinese ones?
KiloOne 02-04-2010, 06:04 AM Yes they are Chinese output, confirmed with my 100mhz digital USB storage scope, although I have yet to translate the data stream.
I have both an 18 inch and a 24 inch and I got them on Ebay recently from seller 800watt.
These are big an heavy calipers, well worth the money, even though they are inexpensive.
By the way I checked my cheap Habor Freight 4 and 6 inch calipers and they are +ve gnd.
BillTodd 02-04-2010, 09:03 AM Yes they are Chinese output, confirmed with my 100mhz digital USB storage scope, although I have yet to translate the data stream.
Great. Keep us informed on your progress and let me know if I can help with modifying the PIC code.
...from seller 800watt.
He's got some nice bits there. (It's a pity it's so expensive to ship heavy goods over to the UK)
KiloOne 02-05-2010, 10:48 AM Bill,
I am stuck because I can't access the dll from vb6, I know that the answer is simple:
Here is the VB6 code I am testing:
Public Declare Function MPUSBGetDeviceCount Lib "mpusbapi.dll" Alias "_MPUSBGetDeviceCount" (ByVal pVID_PID As String) As Long
Global count As Long
Sub OpenMPUSBDevice()
count = MPUSBGetDeviceCount("vid_04d8&pid_003f" & Null) ''ERROR here with Error 49 Bad DLL calling convention
End Sub
Here is what I believe is the C code from the source files for mpusbapi.dll:
DWORD MPUSBGetDeviceCount(PCHAR pVID_PID)
{
DWORD count; // Number of USB device with matching VID & PID
count = 0; // Initialization
for(int i = 0; i < MAX_NUM_MPUSB_DEV; i++)
{
if(MPUSBGetDeviceLink(i,pVID_PID,NULL,NULL,NULL) == MPUSB_SUCCESS)
count++;
}//end for
return count;
}//end MPUSBGetDeviceCount
The DLL routine returns a DWORD which I think is VB6 Long and the argument is PCHAR which I think is a Null terminated string so I added the Null in calling it.
I've tried it many different ways with no luck-- always ' Error 49 Bad DLL calling convention'.
Have you got any thoughts on this?
I have attached the Dll if you want to quickly try this.
Thanks,
Dale
george4657 02-05-2010, 12:34 PM Do a google code search for mpusbapi lang:basic and you will find an example of basic program using this function
page link it gives is no longer valid but all the code is there.
http://google.com/codesearch?q=mpusbapi+lang%3Abasic&hl=en
George
KiloOne 02-05-2010, 12:46 PM Thanks George, never seen that code search before, very useful.
I have already seen that code, it is coded for VB.net (or whatever Microsoft named VB6 successor). Not compatible with VB6, they shouldn't even have had the right to call it VB in my opinion, code is not very convertible.
I copied the code it used to declare and call MPUSBGetDeviceCount and it got the same error, I went digging and found the C code in the dll and tried to fix the problem with the Null and Long.
Dale
BillTodd 02-05-2010, 12:54 PM If memory serves, the ByVal statement should pass a null terminated string to the dll so you shouldn't need to add the termination.
A quick google threw up others having the same problem with the microchip dll (suggesting that it doesn't use standard calling conventions - i.e. not VB compatible)
Might be worth chasing Microchip ???
KiloOne 02-05-2010, 01:04 PM Bill,
Didn't work without Null either, good to know Byval sends it.
I already have a Microchip ticket open on this but haven't had a response yet.
I hope I can use VB6. I never went to VB.net, it was just too different and a money grab. Someday I'll just learn C.
Thanks,
Dale
BillTodd 02-05-2010, 01:18 PM I hope I can use VB6. I never went to VB.net, it was just too different and a money grab. Someday I'll just learn C.
:) Snap !
I tried VB.net as a beta - it was like starting all over again, NOTHING worked !
A friend suggest C# but ... I think my programming days are over (or at least the days of learning a new language are) , I don't get anything out of it any more :(
KiloOne 02-05-2010, 09:40 PM Bill,
Well that was interesting:cool:, I can now send and receive data to the 18F87J50 demo board with a simple VB6 program.:)
The template like code was generated by EasyHID and it uses mcHID.dll.
I just set the VendorID, ProductID, BufferInSize, BufferOutSize.
Then I wrote a little code to toggle the LEDs (on the pic board) every time there is a state change of a switch on the pic board. Read and write accomplished.
Attached is the VB6 project and the dll if anyone wants to 'look' at it.
To run it you need PIC18F87J50 FS USB PIM demo board with 'USB Device - HID - Simple Custom Demo - C18 - PIC18F87J50 PIM.hex' loaded
Now I just have to mesh your 12F675 asm code into the C++ workspace that Microchip uses for the USB pic's. I hope that is not too hard.
:cheers:
Cheers
Dale
KiloOne 02-06-2010, 05:50 PM Bill,
Well I now am able to modify the C code, build, load and run a hex file. I spent a lot of time trying to consolidate all the necessary .c and .h files into the project directory but eventually gave up. In all there are about 16 files loaded or included, wow.
Anyway, I can very easily call an asm function from C or insert asm code inline in C (with a little syntax changing). So I am ready to dive in.
First, I am not sure how not having a +ve gnd on the caliper changes the input signal components. I don't think it does. Would I just use the LED/3.3k components you used?
In your code below it says you are setting the reference voltage to 0.75v but I can't figure out how that is. The B'10100011' sets VRR to low range and VR3:VR0 to 0011 or decimal 3. Doesn't that make the ref voltage = (3/24)*5 = 0.625? I'm not tying to be picky, I just want to be sure that I understand assembly/binary/.... because I am so rusty at it.
Anyway, wish me luck!!:)
Dale
;initialise comparator etc
;
VInit BSF status,RP0 ;select bank 1
movlw B'10100011' ;set Vref ~ 0.75v, Vdd = 5v;(24/5)* 0.75
movwf VRCON
BillTodd 02-06-2010, 07:59 PM Hi Dale, your progress is impressive:)
I'll check the ref value code tomorrow. However, your scale works at 3v from the 2032 cell, so you'll want to set the comparetor threshold higher any way. Similarly, you may need to use 3v zeners (or perhaps green leds) to limit the voltage out of the pic (if the pic runs at 3v, not 5v, you could dispence with the doiodes altogether)
KiloOne 02-06-2010, 08:39 PM Yep, I wish I had a 3V signal level, then I would just have TTL input levels and use digital I/O ports on the Pic.
Not to be, even though the battery is 3v, the output signal is only 1.5v.
One of the main things I need to do is get rid of the battery and get the 10 microamps I need to power the caliper form the USB. I was just going to use a 3V zener to power it with a 100 uF cap on it.
I will run the Pic on 5v from the USB.
Now this is a stupid question, why can't I just put the data lines to the comparator thru 10k resistors and forget the diodes?
Thanks,
Dale
P.S. I spoke too soon on how easy it was to add asm to C18. When I actually try it I get syntax error at _asm. Supposedly you just put ams between _asm and _endasm, oh well, more grief (3 hours so far on this one). The more I look at the C code the more I might try just doing it.
BillTodd 02-07-2010, 07:32 AM Yep, I wish I had a 3V signal level, then I would just have TTL input levels and use digital I/O ports on the Pic.
Not to be, even though the battery is 3v, the output signal is only 1.5v.
That's interesting. I have noticed how the scales are fairly sensitive to supply voltage, I wonder if running things at 3v has given the designer the opportunity to stabilise the supply?
One of the main things I need to do is get rid of the battery and get the 10 microamps I need to power the caliper form the USB. I was just going to use a 3V zener to power it with a 100 uF cap on it.
Or a simple resistive divider and a hundred nF would do @ 10uA
Now this is a stupid question, why can't I just put the data lines to the comparator thru 10k resistors and forget the diodes?
I added the LEDs to limit the voltage at the scale inputs (a red led has a Vfwd of about 1.2v, a couple of forward biased silicon diodes would have worked just as well).
The scales I used have shared lines for the outputs and control buttons, so to change mode (e.g. switch to fast read mode for a DRO) you have to raise the level on the data and clock lines to the supply rail in an appropriate order by driving them from the o/p of the PIC. I found that If I raised them above 1v5 the scale latched up.
[edit]
BTW I checked the comparator setting; You are right I have set it for 0.625v not 0.75 - I can only think it was something I tweaked during development and forgot to correct the documentation :(
KiloOne 02-07-2010, 09:02 AM ...I wonder if running things at 3v has given the designer the opportunity to stabilise the supply?
Probably, but if I just had 2.25V I would maybe risk trying TTL. Most likely a backward compatibility issue.
Or a simple resistive divider and a hundred nF would do @ 10uA
The only reason I said 100mF was because that is what the Shumatech people are doing. Any Idea what frequency noise glitches you are having to filter out?
I added the LEDs to limit the voltage at the scale inputs (a red led has a Vfwd of about 1.2v, a couple of forward biased silicon diodes would have worked just as well).
Ah yes, I remember you saying this earlier, sorry. Isn't the power to light up your LEDs coming from the caliper outputs? I guess whatever that current is, it is not pulling the signal down.
I found that If I raised them above 1v5 the scale latched up.
The + data out line is 1.5v and it does not lock up when I trigger Zero and Mode with 1k resistor, although I don't see any obvious thing that the Mode trigger does. Yeh!:D
...something I tweaked during development and forgot to correct the documentation
No problem I do it all the time, more often I don't even rem my code. Shame Shame.
Back to assembly code. VB6 is so way far ahead of this C18 stuff in terms of syntax checking, error documentation, user interface, debugging ... it is laughable:). It turns out that the error I was getting was pointing me to the _asm line that I added and it was actually not a syntax error but some other error having to do with memory allocation I was trying in the NEXT line.
I was trying to declare all the same variables that you did by using inline asm insertion. Eventually I had to just declare them in C.
The question I have come up with in doing this is that I don't know how to declare rxbuff and vdata. You use 2 and 4 consecutive bytes for these but you only reserve the first byte in memory. What will stop the following 1 and 3 memory bytes from being used by some other code I didn't write without my knowledge?
Would I have to declare them as a 2 byte INT and 4 byte LONG in C and if so, does that mean I could not use the asm code of say vdata+2 to access the 3rd data byte in vdata? If not I guess I would have to go with some weird byte addressing scheme.
Sorry for being such a pain.(chair)
Dale
BillTodd 02-07-2010, 02:50 PM Any Idea what frequency noise glitches you are having to filter out?
The glitches look like spikes on the data of clock o/p. They could be caused by supply noise or possibly interrupts or some other software reason
The question I have come up with in doing this is that I don't know how to declare rxbuff and vdata. You use 2 and 4 consecutive bytes for these but you only reserve the first byte in memory. What will stop the following 1 and 3 memory bytes from being used by some other code I didn't write without my knowledge?
I cut my teeth on 6502 & z80 assemblers that had few of the bells and whistles of MPASM so I have not used the higher level declaration options.
I guess you could declare the buffer spaces as int or long or pretty much anything that is easy to access (you'll need to do some bit manipulation), just check the byte order is the same in asm and C or it'll cause confusion when you try to decode it. As to stopping the variables being over written, there should be some way of making them static in C.
vdata+2 should work as long as the byte order is correct (i.e. (vdata )<(vdata+1))
Sorry for being such a pain.
No problem - I'm just pleased someone else is using my code :)
|
|