|
|
View previous topic :: View next topic |
Author |
Message |
smitty1276
Joined: 08 Dec 2005 Posts: 4
|
A/D Problem? (Newbie) |
Posted: Thu Dec 08, 2005 3:35 pm |
|
|
First of all, I should warn everyone that I am not exactly a "hardware guy", so I apologize in advance for anything stupid that I say.
I am working on a device built around an 16F877A (actually a DLP2232PB usb adapter/programmer) which communicates with a controlling PC via Bluetooth using a RS232 Smart Module and max232. (I hope this is making sense... ).
The code I am writing simply loops repeatedly, checking for input command bytes, and reading the temperature of a thermal pad off of the a/d. If the pad is below a target temperature, it's power is flipped on. If the pad is above the target, it is turned off.
If I comment out the read_adc() calls, everything that isn't temperature related does what it is supposed to (there are some other things that the device does, most of which involve setting some pin or another high or low when commanded to do so, etc). If I actually call read_adc(), everything ELSE stops working.
That is, it will continue to loop and read temperatures and maintain the temperature of the pad correctly, but will not process any more incoming commands. This is probably an I/O problem of some sort.
Does anything look wrong in these small snippets that might explain any of this, if I even made sense? Bear in mind that the code doesn't necessarily appear linearly like this... the read_adc() call, for example, is in a function that is dedicated to the heat processing.
Code: | #include <16F877A.H>
#device ADC=10
#fuses HS,WDT,NOPUT,NOBROWNOUT,LVP,NOWRT,NOPROTECT
#use delay(clock=20000000,restart_wdt)
#use rs232(STREAM=serial,BAUD=115200,XMIT=PIN_C6,RCV=PIN_C7,PARITY=N,BITS=8)
...
//Set up the UART
setup_uart(115200, serial);
// Setup the ADC...
setup_adc_ports(AN0_AN1_VSS_VREF);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(10);
...
// The heat pad is read like so... performed every pass...
heatPadState.currentTemp = (float)read_adc() / TEMP_DIV;
...
// Ridiculously simple input check... performed every pass...
void readPacket()
{
char inChar;
// Check for waiting data...
while (kbhit() != 0)
{
inChar = getc();
// If the char is '*' it signifies the end of a packet...
if (inChar == '*')
{
packet.buffer[packet.numBytesRead] = '\0';
packet.valid = true;
return;
}
else
{
packet.buffer[packet.numBytesRead] = inChar;
packet.numBytesRead++;
}
}
}
|
I am hoping that something here will be immediately obvious to you guys who deal with these things regularly. Thanks in advance for any help. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 08, 2005 3:54 pm |
|
|
The floating point math associated with the read_adc() is going to
take many microseconds to do. Your baud rate is fairly high.
I think it's likely that you're getting an overrun error in the hardware
UART. This will cause it to lock up.
You can check if this is happening in a couple ways:
1. Remove the floating point math and just do simple read_adc().
or
2. Add the ERRORS directive to your #use rs232() statement.
This will clear any overrun errors that occur. Though, you'll
still lose the character.
A couple questions:
1. Are you using a Low Voltage programmer (such as TLVP ?)
If not, then change the LVP fuse to NOLVP.
2. You're using WDT. Do you have a restart_wdt() statement
somewhere in your program ? Consider turning off the WDT
while you're debugging your program. |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
Re: A/D Problem? (Newbie) |
Posted: Thu Dec 08, 2005 3:59 pm |
|
|
smitty1276 wrote: | [code]setup_adc_ports(AN0_AN1_VSS_VREF);[code] |
What is your Vref pin connected to? You have set up your A/D to read the voltage between Vss and Vref. Vss corresponds to 0 A/D counts and Vref corresponds to 1023 A/D counts. I'm not sure if this is the root of your problem, but there might be a hardware/software bug here. |
|
|
smitty1276
Joined: 08 Dec 2005 Posts: 4
|
|
Posted: Thu Dec 08, 2005 4:03 pm |
|
|
Thanks PCM, I'll definately experiment with that floating point thing. However, there is a considerable amount of code executed on each pass, so I'm not sure if removing the cast to a float will improve the overall situation. Definately worth a try though.
Regarding the low voltage programmer... I am using a DLP-2232PB ( http://www.dlpdesign.com/usb/2232pb.shtml), and I'm really not sure if this is a LVP or not. Probably not, so I'll try that also. |
|
|
smitty1276
Joined: 08 Dec 2005 Posts: 4
|
Re: A/D Problem? (Newbie) |
Posted: Thu Dec 08, 2005 4:09 pm |
|
|
kender wrote: | smitty1276 wrote: | [code]setup_adc_ports(AN0_AN1_VSS_VREF);[code] |
What is your Vref pin connected to? You have set up your A/D to read the voltage between Vss and Vref. Vss corresponds to 0 A/D counts and Vref corresponds to 1023 A/D counts. I'm not sure if this is the root of your problem, but there might be a hardware/software bug here. |
Hmm... well, we have an engineer here who is putting the hardware together. I'll get back to you tomorrow morning for the answer to your specific question.
However, the actual temperature is being read correctly. If the particular hardware/software bug to which you are referring existed, would it still correctly read temps but cause all other functionality to stop working? (Essentially, it ceases to respond to incoming commands...) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 08, 2005 4:32 pm |
|
|
I don't see an on-board source for the 13v used in High Voltage
programming in their schematic, so it likely is using LVP mode. |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
Re: A/D Problem? (Newbie) |
Posted: Thu Dec 08, 2005 5:47 pm |
|
|
smitty1276 wrote: | However, the actual temperature is being read correctly. |
Then your voltage reference is most likely correctly connected. |
|
|
smitty1276
Joined: 08 Dec 2005 Posts: 4
|
|
Posted: Fri Dec 09, 2005 11:31 am |
|
|
Thanks for the help so far guys... I think things are going to work correctly after I clear up a couple of problems (fingers crossed).
I do have another question here...
This snippet of code:
Code: |
heatPadState.targetTemp =
packet.buffer[PKT_FIRST_DATA_BYTE] * TEMP_DIV;
printf("Temp byte: %lu / %lu ", (int16)packet.buffer[PKT_FIRST_DATA_BYTE], heatPadState.targetTemp); |
Should set the target temperature of the heat pad to the value sent... I removed the floating point math as suggested, so now I am dealing in the units used by the a/d (in this case, divisions of 4). So the first line should take an incoming value, say 100 for example, and store 400 in the variable heatPadState.targetTemp, which is defined as an int16.
The next line, however, prints the incoming value and the stored value, which are coming out wrong.
If I send a 100, it prints "Temp byte: 100 / 144". If I send a 120, it prints "Temp byte: 120 / 224".
Does anyone have any idea why it might be storing something other than what I tell it to store?
EDIT: Apparently it didn't like the implicit cast to an int16. I explicitly cast it and it now works.
Thanks for the help guys. |
|
|
|
|
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
|