![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
wazzy
Joined: 27 Feb 2005 Posts: 5
|
PIC16C765 adc help needed for a nvist mcu programmer |
Posted: Sun Feb 27, 2005 4:35 pm |
|
|
I am trying to make a usb joystick using the pic16c765 mcu. I have a mini analog joystick and i am feeding it into the mcu to control the directions.
The mcu is connected to an external 6Mhz clock and the joystick basically gives -x/-y direction for 1 volt, +x/+y for 3 volts and 2volts for no motion.
I am directing the code to use the internal oscillator for the a2d and i inserted a delay of 10 us before reading the value.
The problem is that one of the values is always one and the other is always zero. the always high value would sometimes spike to zero in the case of rigorous movement in that direction. but never long enough to stop the motion.
Now my question is this, the adc using the internal oscillator requires that the mcu be in sleep, i think i am doing that using the delay. is the delay too short, too long? also, the adc doesnt differ to the Vref at all. I understand that it should. The only difference is that the Vref is supplied from an external voltage and the ground terminals are all common. This is all for experimental purposes and later on the same voltage source will be split and a voltage splitter will be placed before the Vref to shed it down to 3.5v. Could that be the problem?
Any help and/or explanation of how the adc works and how so the proper connection should be made would be highly appreciated.
Thanks alot for taking the time to read this lengthy post. And thanks in advance for your help.
![Laughing](images/smiles/icon_lol.gif) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 27, 2005 10:37 pm |
|
|
You're trying to do several new things at once. You should start
with a simple test program (like I always say).
Put a trimpot (1K to 10K will work) on AN0 of the 16C765.
This is pin 2 on the 40-pin DIP package.
Connect one end of the trimpot to your Vdd voltage (is it +5v
or +3.3v ?). Connect the other end to ground. Then connect
the wiper (the center tap) to pin AN0.
Run the following program. Watch the results on your terminal
window. As you turn the trimpot, you should see hex values in
the range from 0x00 to 0xFF.
Note: I don't have a 16C765 to test this program, but I believe
it should work.
Code: | #include <16C765.h>
#fuses EC, NOWDT, NOPROTECT
#use delay(clock = 6000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//--------------------------------------------
void main()
{
int8 result;
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
while(1)
{
result = read_adc();
printf("result = %X \n\r", result);
delay_ms(500);
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
wazzy
Joined: 27 Feb 2005 Posts: 5
|
more Q's |
Posted: Mon Feb 28, 2005 12:42 am |
|
|
Thanks for your code... but here is a quick Q regarding it, you specify three ports when you set up the adc, why is that when, as far as i can see you are using only one?
Another question is, you do not seem to have anything connected to Vref, nor is it specified. Will it automatically use the Vdd as Vref?
and my Vdd is 5 volts being fed into the mcu via the computers USB.
The thing is that i already have the USB protocol setup and working fine, and i have been able to simulate the joystick through code. This is actually almost the last step as i just need the input now.
also, i realize you delay for 500us, i only delayed for 20 and i was getting garbage, could that be the reason?
Thanks alot for your help and reply. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 28, 2005 1:21 am |
|
|
Quote: |
Here is a quick Q regarding it, you specify three ports when you set up
the adc, why is that when, as far as i can see you are using only one?
Another question is, you do not seem to have anything connected to Vref,
nor is it specified. Will it automatically use the Vdd as Vref? |
You can't make any arbitrary selection of pins into analog pins. You have
to use the groupings that are specified in the data sheet. Look at page
93 (the acrobat reader page) of the 16C765 data sheet. There is a
chart titled "Register 12-2 A/D Control Register 1 (ADCON1:9Fh)".
It shows the allowable combinations of analog and digital pins.
Look in the 16C765.H file to see the constants that CCS uses with the
setup_adc_ports() function. Those constants correspond to the
configurations shown on that page of the data sheet.
Quote: | Another question is, you do not seem to have anything connected to Vref, nor is it specified. Will it automatically use the Vdd as Vref? |
Look at the same chart that I referred to above. It also specifies the
reference that is used with each A/D configuration. Look at the constants
in the 16C765.H file. You'll see that some of them end with _VREF.
These are the ones that have Vref on the AN3 pin. If _VREF is not
on the constant, then Vref is VDD.
Quote: | also, i realize you delay for 500us, i only delayed for 20 and i was getting garbage, could that be the reason? |
Actually, I'm not using 500 microseconds, I'm using 500 milliseconds.
That's a 1/2 second. I'm doing that to allow some time between updates
of the display while the user turns the trimpot wheel. It makes it easier
to watch the changes if the data is updated slowly rather than scrolling
off at high speed. |
|
![](templates/subSilver/images/spacer.gif) |
wazzy
Joined: 27 Feb 2005 Posts: 5
|
adc still not working |
Posted: Mon Feb 28, 2005 7:36 am |
|
|
Thanks for the help.. But I think my problem is setting the adc clock. Im providing the the mcu with a 6 MHz external clock. Internally, that is modified to 24 MHz. So when i use the setup_adc() function, I'm not sure whether to provide ADC_CLOCK_INTERNAL or ADC_CLOCK_DIV_32.. The ADC_CLOCK_INTERNAL requires that the mcu goes into sleep throughout the entire conversion process (as mentioned in page 96 of the PIC16C765 datasheet, beneath the table, note 2). So is the problem that I'm not going into sleep mode before the conversion? If I add the sleep command before the read_adc(), will the mcu wake up when the conversion is done (that is, is finishing the conversion considered an external event that wakes up the mcu)? Or should I not use the ADC_CLOCK_INTERNAL at all?
One other thing, do I need to delay at all when using the read_adc()? or does the function delay by itself until the conversion is done?
Anyway, here is the part of my code that deals with the adc. Maybe you can figure out the problem!
Code: |
setup_adc_ports(A_ANALOG_RA3_REF);
setup_adc(ADC_CLOCK_INTERNAL);
temp=0;
out_data[0]=0;
out_data[3]=0;
while(usb_enumerated()) {
set_adc_channel(0);
temp=read_adc();
if (temp>170) //thats the positive value
out_data[1]=1;
else
if (temp<110) //thats the negative value
out_data[1]=255;
else
out_data[1]=0; //otherwise, just zero
set_adc_channel(1);
temp=read_adc();
if (temp>170) //thats the positive value
out_data[2]=1;
else
if (temp<110) //thats the negative value
out_data[2]=255;
else
out_data[2]=0; //otherwise, just zero
usb_put_packet(1,out_data,4,TOGGLE);
delay_ms(10);
}
|
What happens is that the first reading (channel 0) always goes into positive.. Sometimes, as I mentioned, it goes into negative on very rigorous motion. On the other hand, the second reading (channel 1) always goes into negative.. That value never goes into positive, no matter what we do!
So I hope this could clear things out a bit.
Again, thanks for your help. I really appreciate it! |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Feb 28, 2005 8:41 am |
|
|
The ADC process, involves two seperate 'phases' The reading itself, is automatically timed by the 'read_adc' process. However this is 'reading' the voltage held on an internal capacitor in the chip, which is connected to the incoming signal by the 'set_adc_channel' command. This capacitor takes time to charge up, and so this has to be done seperately in your code, before taking the reading.
Approach it slightly the other way round. As the penultimate instruction, in your sampling code, in front of the delay, set_adc_channel(0). This way, when you arrive at the start of the code, the capacitor is already always charged to the adc0 voltage. You can then read this immediately, and immediately set_adc_channel(1). Now the 'if' statements provide some delay, but in the shortest 'route' perhaps only a couple of uSec. Add a delay_us to bring this up to about 10uSec (assuming the voltage source has a low enough impedance to charge the capacitor in about 10uSec), then take the second reading.
The read_adc function, self-times the 'reading', but not the acquisition.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
rwyoung
Joined: 12 Nov 2003 Posts: 563 Location: Lawrence, KS USA
|
|
Posted: Mon Feb 28, 2005 8:53 am |
|
|
OK, time for a game of "Let's Learn to Read Microchip Datasheets"! Yea!
ADC clock issue:
Reading through all the great stuff in the ADC section we eventually get to a portion titled "A/D Acquisition Requirements". Here we get to learn how fast the ADC can really run. Equation 12-1 goes into great and painfull detail on how to calculate this for a given range of temperatures and a given source resistance. Also you are refered to the Midrange Reference Manual (a definate read if you plan to be using the PIC16s). In general, for the average application assume a worst case of TACQ=16us.
Next we dig into the section titled "Selecting the A/D Conversion Clock". One of the first things we read is that the PIC is going to need 9.5TADs to complete a conversion. TAD must be at least 1.6us to get the FULL 8 bits. If it is less than that, the ADC will still work but we aren't guaranteed to full 8 bit accuracy. Since you are running a joystick you can probably survive a little loss of accuracy. This makes your choices a little easier, pick the 32TOSC option for your TAD resulting in TAD=1.33us for your 24MHz clock speed.
One last issue is the changing from channel to channel during reads. The PIC has a single ADC with a multiplexer in front. This means you need to allow time for the mux to switch as well as the sample-and-hold cap to charge/discharge to its new level before you start a new conversion. Refer back to equation 12-1 and its associated figure. You should allow at least TACQ time to pass after changing channels before you start an ADC cycle.
Next we get to read a little bit about the "read_adc()" function in the CCS manual. I'll leave that as an exercise for you. But if you just say "x=read_adc()" the PIC will start the ADC cycle and just idle as it reads the GO/DONE- bit. Once low, it will return the ADC value. There are other things you can do such as just start the ADC and move on to other calculations on old data or housekeeping chores and then get the new data yourself. Or you can set up an interrupt. Lots of things to play with. Just read the CCS manual to get the syntax.
Also look at the LST file created by the compiler and compare that to what the part datasheet says. Many times that makes the situation more clear. _________________ Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month! |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|