PDA

View Full Version : 12F675 and LM35 coding issue



Bobbo_ZA
- 5th March 2010, 09:53
Hi All,

I'm a bit of a n00b when it comes to the PIC world, :-).

I have developed previously in C, Cobol, VB6 (and .net) and C++, however I have decided to use PIC Basic for my embedded projects. I started with the simple blink (with and without button input) with a few LEDs hanging off the various ports, then worked up to rotating beacons (using PWM).

My next mini learning project is to connect an LM35 to a 12F675. Along with the LM35 im connecting 3 LEDs, one white, one blue and one red simply to indicate a range of temps per color (i.e. if Temp < 30 then light the white LED etc) - Something I have got working through my Arduino and want to move to a more cost effective platform, :-).

I have spent a few evenings mulling over it and changing the code, flashing and testing with not much success. I think my issues are stemming from my lack of understanding of the various registers used i.e. ANSEL, TRISIO etc, although I think I have read the datasheet correctly its still not giving me the desired result.

Below is the code I have so far, please could you look and advise where I am going wrong?



'Using PIC 12F675 with White LED connected to Pin 7, Blue LED on Pin 6,
'Red LED on pin 7. Vdd is supplied as a regulated 5v to pin 1, Ground to pin 8.
'LM 35 connected to Vdd and Ground + Centre pin connected to Pin 3 (AN3)
'Pin 4 disconnected - Have tried connecting to Vdd with 10K res and turning MCLR_on with no sucess

@ device pic12F675,INTRC_OSC,wdt_off,pwrt_on,protect_off,MC LR_off
DEFINE CHAR_PACING 1000
DEFINE OSC 4 'Set internal osc. To 4MHz

'---------Define ADCin Parameters
DEFINE ADC_BITS 10 'set number of bits in result
DEFINE ADC_CLOCK 3 'set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 'Set sampling time in uS

'---------Define Vairables
samples VAR WORD ' Multiple A/D sample accumulator
sample VAR BYTE ' Holds number of samples to take
temp VAR BYTE ' Temperature storage
' clear Samples

LED0 Con 0 ' GPIO.0 = White LED
LED1 CON 1 ' GPIO.1 = Blue LED
LED2 CON 2 ' GPIO.2 = Red LED

'--------Configuring I/O PORTS
TRISIO = %010000 'set GPIO.0, GPIO.1, GPIO.2 as output (LEDs) & GPIO.4 as input
ANSEL = %00111000 ' Set ADC clock = Frc, GPIO.4, 1 = A/D
ADCON0 = %10000000 ' Right justify, use Vdd as Vref
CMCON = 7

'---------Main Program
'Flash White LED on Start
HIGH LED0
Pause 500
LOW LED0

TEMP_READ: 'Subroutine to measure temp
temp = 0 'Clear temp register
samples = 0 'Clear samples register
FOR sample = 1 TO 20 'Take 20 samples
ADCIN 3, temp ' Read AN3 into temp variable
samples = samples + temp
PAUSE 250 ' Wait 1/4 seconds per reading
NEXT sample
temp = samples/20 'Average over 20 samples (Every 5 seconds)
temp=(temp* 10)/2

if TEMP <20 then 'Less than 20deg - White LED
HIGH LED0
LOW LED1
LOW LED2
GOTO TEMP_READ
ENDIF

IF TEMP >20 AND temp <30 then 'Between 20deg and 30deg - Blue
LOW LED0
HIGH LED1
LOW LED2
GOTO TEMP_READ
ENDIF

IF TEMP >30 then 'Greater than 30deg - Red
HIGH LED2
LOW LED1
LOW LED0
GOTO TEMP_READ
endif

END

HenrikOlsson
- 5th March 2010, 10:31
Hi,
You're not saying what the problem is, just that it doesn't do what you expect. As it looks quite alright to me I'm guessing you have problem with actually getting a reading from the ADC.

ADCON0.0 turns on/off the ADC and you have it set to '0' = OFF and I'm not sure if the ADCIN command handles that bit automatically or not. Try setting it to '1' and see what happens.

If your problem isn't related to the actual ADC then please elaborate a bit on what the problem is.

/Henrik.

Bobbo_ZA
- 5th March 2010, 11:06
Sorry, :-) you are right. Basically, its not doing anything currently. I have however checked the Data sheet and you are right, so I have changed the ADCON0 as follows: ADCON0 = %10001101, this should give me

Bit - Setting
0 - 1 = A/D Operating
1 - A/D conversion Bit (I assume ADCIN would set this to 1 when running)
2-3 - 11 = Channel 3 (AN3 / GPIO4)
4-5 - Not Used
6 - Vref, 0 = Vdd
7 - 1= Right Justify

However, even after this change and running it in the simulator (I don't have my breadboard etc here at work) it still does not even light up the <20 LED, :-(

Kind Regards
Rob

fratello
- 5th March 2010, 11:57
'Using PIC 12F675 with White LED connected to Pin 7, Blue LED on Pin 6,
'Red LED on pin 7. Vdd is supplied as a regulated 5v to pin 1, Ground to pin 8.
'LM 35 connected to Vdd and Ground + Centre pin connected to Pin 3 (AN3)
'Pin 4 disconnected - Have tried connecting to Vdd with 10K res and turning MCLR_on with no sucess

@ device pic12F675,INTRC_OSC,wdt_off,pwrt_on,protect_off,MC LR_off
DEFINE CHAR_PACING 1000
DEFINE OSC 4 'Set internal osc. To 4MHz

'---------Define ADCin Parameters
DEFINE ADC_BITS 10 'set number of bits in result
DEFINE ADC_CLOCK 3 'set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 'Set sampling time in uS

'---------Define Vairables
samples VAR WORD ' Multiple A/D sample accumulator
sample VAR BYTE ' Holds number of samples to take
temp VAR BYTE ' Temperature storage
' clear Samples

LED0 Con 0 ' GPIO.0 = White LED
LED1 CON 1 ' GPIO.1 = Blue LED
LED2 CON 2 ' GPIO.2 = Red LED

'--------Configuring I/O PORTS
TRISIO = %010000 'set GPIO.0, GPIO.1, GPIO.2 as output (LEDs) & GPIO.4 as input
ANSEL = %00111000 ' Set ADC clock = Frc, GPIO.4, 1 = A/D
ADCON0 = %10000000 ' Right justify, use Vdd as Vref
CMCON = 7

'---------Main Program
'Flash White LED on Start
HIGH LED0
Pause 500
LOW LED0

TEMP_READ: 'Subroutine to measure temp
temp = 0 'Clear temp register
samples = 0 'Clear samples register
FOR sample = 1 TO 20 'Take 20 samples
ADCIN 3, temp ' Read AN3 into temp variable
samples = samples + temp
PAUSE 250 ' Wait 1/4 seconds per reading
NEXT sample
temp = samples/20 'Average over 20 samples (Every 5 seconds)
temp=(temp* 10)/2

if TEMP <20 then 'Less than 20deg - White LED
HIGH LED0
LOW LED1
LOW LED2
' GOTO TEMP_READ
ENDIF

IF TEMP >20 AND temp <30 then 'Between 20deg and 30deg - Blue
LOW LED0
HIGH LED1
LOW LED2
' GOTO TEMP_READ
ENDIF

IF TEMP >30 then 'Greater than 30deg - Red
HIGH LED2
LOW LED1
LOW LED0
' GOTO TEMP_READ
endif

goto temp_read

END

Charles Linquis
- 5th March 2010, 13:32
It loloks to me that you are taking the 10-bit A/D samples and putting them in BYTE variable called TEMP. Changing TEMP to a word should certainly get you one more step.

Acetronics2
- 5th March 2010, 14:04
Hi, Bobbo

Your main problem was scaling temps before displaying ...

try this one :



'************************************************* ***************
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2010 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 05/03/2010 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
'* Name : Temp 675'Using PIC 12F675 with White LED connected to Pin 7, Blue LED on Pin 6,
'Red LED on pin 7. Vdd is supplied as a regulated 5v to pin 1, Ground to pin 8.
'LM 35 connected to Vdd and Ground + Centre pin connected to Pin 3 (AN3)
'Pin 4 disconnected - Have tried connecting to Vdd with 10K res and turning MCLR_on with no sucess

@ device pic12F675,INTRC_OSC,wdt_on,pwrt_on,protect_off,MCL R_off

'DEFINE CHAR_PACING 1000
DEFINE OSC 4 'Set internal osc. To 4MHz

'---------Define ADCin Parameters
DEFINE ADC_BITS 10 'set number of bits in result
DEFINE ADC_CLOCK 3 'set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 'Set sampling time in uS

ANSEL = %00111000 ' Set ADC clock = Frc, GPIO.4, 1 = A/D
ADCON0 = %10001100 ' Right justify, use Vdd as Vref ' Select channel 3 !!!

CMCON = 7


'---------Define Vairables
samples VAR WORD ' Multiple A/D sample accumulator
dummy var word ' DIV32 intermediate value
sample VAR BYTE ' Holds number of samples to take
temp VAR BYTE ' Temperature storage ... might be a WORD !!! ( 0 - 1023 !!! )

CLEAR ' clear Variables

LED0 Con 0 ' GPIO.0 = White LED
LED1 CON 1 ' GPIO.1 = Blue LED
LED2 CON 2 ' GPIO.2 = Red LED

'--------Configuring I/O PORTS
GPIO = 0
TRISIO = %010000 'set GPIO.0, GPIO.1, GPIO.2 as output (LEDs) & GPIO.4 as input

'---------Main Program
'Flash White LED on Start

HIGH LED0
Pause 500
LOW LED0

While 1

TEMP_READ: 'Subroutine to measure temp input = 10 mv/°C ~250 mv

temp = 0 'Clear temp register
samples = 0 'Clear samples register

FOR sample = 1 TO 20 'Take 20 samples
ADCIN 3, temp ' Read AN3 into temp variable result is ~ 50 ( .25 / 5 * 1024 )
samples = samples + temp
PAUSE 12 ' Wait 1/4 seconds per display ... (20 x 12 ms )
NEXT sample

temp = samples/20 'Average over 20 samples (Every 5 seconds) result is ~ 50
' temp=(temp* 10)/2 ' Result is 250 ... may overflow !!! so, the mult is no use !!!

'************************************************* ******************************
' Trim to scale
'************************************************* *******************************

Dummy = 500 * temp ' 500 = 5000 mv full scale / 10 mv per degree
temp = DIV32 1024 ' Number is Deg C Now ...

'************************************************* *******************************

SELECT CASE temp

CASE is < 20 'Less than 20deg - White LED

HIGH LED0
LOW LED1
LOW LED2


CASE is < 31 'Between 20deg and 30deg - Blue

LOW LED0
HIGH LED1
LOW LED2


CASE is < 45 'Greater than 30deg - but less than 45 deg Red

HIGH LED2
LOW LED1
LOW LED0

CASE Else ' Too cold !!! or dangerously hot ... let's blink everyting !!!

HIGH LED0
HIGH LED1
HIGH LED2

PAUSE 250

LOW LED0
LOW LED1
LOW LED2

END SELECT

wend

END



Interesting parts have been explained ...

now, have a good bath ... you've sweat a lot on this one ... ROFL.

Acetronics2
- 5th March 2010, 15:07
It loloks to me that you are taking the 10-bit A/D samples and putting them in BYTE variable called TEMP. Changing TEMP to a word should certainly get you one more step.

Hi, Charles

The point is interesting as the maximum ADC value WITH THIS SENSOR ... will be ~ 256, and always far from the actual use of the sensor.

so, we could use ADRESH as an open line indicator ....

Alain

Charles Linquis
- 6th March 2010, 22:00
LM35s don't have much output current, so you have to be careful with the load, but if you put a 100K ohm pull-up resistor to Vref, then you could detect an open sensor.

Also look at the data sheet. They don't like capacitive loads, so if you have them located more than a few feet from the PIC, you should put a small resistor in series with the LM35 output pin.

Bobbo_ZA
- 8th March 2010, 11:30
Hectic weekend and I was starting to have withdrawal symptoms for my PIC and breadboard, :-)

I didn't get a chance on the weekend to try this code, however, I must say, I struggled for ages trying to work out how to use the CASE statement and your example above has shown me where I went wrong.

I have run the example in the simulator (I really need to start bringing my board and programmer to the office, :-) ) however, even with the pause set to 1 it seems to take forever to get through it - thus taking 20 samples @ Pause 250 each time takes hours, :-( - I even tried to set the sim to run Ultra fast, however it still takes ages to run the 20 samples. Looks like im going to have to run it on the chip tonight.

Something im trying to get right in my head: If the LM35 outputs 10mv per deg, on a 5v reference, would 0deg be 2.50V or would the 2.50V be at the mid point of the units full range (110 to -40) i.e. 34Deg C? The data sheet does not seem to be this specific.

Acetronics2
- 8th March 2010, 12:28
I have run the example in the simulator


Vade retro, Satanas ... simulators are TOYS !!!

Simulator ( which one ... might I understand ??? ) is a tool that doesn't "run" @ real speed ... so, pauses have to be divided per 50 or 100 not to become mad ... or even, have to be commented out !!!

so, forget about this sim when some "pause" statements are there ...

the program runs fine here ( I made a small demo where a counter increases temp from 0 to 100 instead of the 20 adc measures - was to verify the SELECT CASE structure, which is slightly different from "C" ... )

for the LM35 ... take it simple !!! :

0v for 0°C
0.01v for 1°C
0.10v for 10°C
1.00v for 100 °C
1.50 v for 150°C ... which is the maximum !!!

so, 2.50 v is a fried chip !!!

on a 5v00 ref ... 1.00v will show 1.00v / 5.00v x 1024 = 204 adc counts ... ( 1024 steps for full scale )



just Work with REAL chips in a REAL World ... you'll get TRUE results ...

Alain

Bobbo_ZA
- 8th March 2010, 18:04
Right, sitting on the couch @ home and was about to post about a strange result I was getting (unexpected LED lighting up)...until I checked my wiring again and I found the breadboard was still swapped from when I was doing the PWM routines with the LEDs, :-).

Just checked with my DMM and it's 100% spot on, will adjust the CASEes to accommodate the 3 ranges I need and move it to a PCB, :-)

Just wanted to say a really BIG thank you to everyone who took the time to help a newbie like me see the light (hehe no pun intended).

I've decided to waterproof the LM35 and place it in the bath to show my 3yr old daughter when the water is too hot to touch - although she knows not to touch unless me or my wife has checked it first.

My next project will be to take an input from my RC transmitter and drive a servo to start with, think I'm going to have to do quite a bit of reading, :-)

Once again, thank you Alain, Fratello, Charles and Hendrik, appreciate the assistance - a couple of light bulbs have gone on in my head, looking forward to the journey PICs might lead me on.

mackrackit
- 8th March 2010, 19:48
Be careful showing little ones you putting something in the bath with wires attached.

Daddy did it with his gadget, I wonder what the radio sounds like under water....

Bobbo_ZA
- 9th March 2010, 06:36
Hi Dave, point taken , :-), will make sure its enclosed and placed well before she sees it. Although when she was 2 she dropped a doll in by accident and since then has learn't not to put anything in the water unless its classified as a bath toy.

Acetronics2
- 9th March 2010, 08:38
Hi, Bobbo

one of our reviews ( Electronique pratique ) raised such a gadget :

- LM339 comparator and NTC
- Packed into a plastic photo roll box
- 2 electrodes + a Darlington trans. to power on the device when dipped into the bath ... ( auto shut off with the towel ! )
- powered with 3x2 small round Li batteries ...

Do not ask me the scheme ... i do not have it !!!
http://www.electroniquepratique.com/detail.php?idMg=29&id=316
http://www.electroniquepratique.com/detail.php?idMg=42&id=505

Alain

Bobbo_ZA
- 10th March 2010, 09:00
Now there's an awesome idea, will work out a way to waterproof the LM35 out the bottom of the case.

Need to also work a way where you can press a button and the device will stay on for X number of minutes and then either sleep or turn off. Then she can press the button, drop it in and watch the colors, of course she will be taught that it is an "Authorized" bath time device, ;-)

BTW, last night I managed to read the input signal from my RC Transmitter (Ok, pulsin is not so hard) from 2 channels and drive 3 different items as follows:

1. LED for testing purposes - easy
2. Pass through for the servo control
3. Glow igniter (proportional depending on the throttle location as well as always on depending on the Gear channel switch) +-3A load - Running through a FET - I learn't how to use these in 1 night, :-) I'm quite chuffed to understand how these work now, it opens up a range of possibilities as now I can switch fairly high loads from the PIC.

Thanks Alain, I noticed you are on RC Groups as well, hope to bump into you there as well in the future, I'll begin posting my autopilot build there soon, planning to use PICs as fail safes for the main navigation / stabilization hardware, :-)

Acetronics2
- 10th March 2010, 09:42
Hi, Bobbo

For the Glow-igniter, I've published an advanced one ... several years ago.

Article is written in French ( ... ! ) so, the question ...

Do you read French ??? ( even under torture ...)

Alain

Bobbo_ZA
- 10th March 2010, 13:45
Alain,

My French is nowhere near as good as your English, :-)

Thankfully, the internet has given us google translate which works quite well with french and where it stumbles I can normally work out the meaning when put into the correct context.

I've had a look around but am a bit confused around 2 things.

1. I'll need a jumper to allow the user to input "Programming mode" - Not sure where to put it, would GP3 with a pulldown res work or can I use any other GP?
2. Once I have read the value I can flash the LED a couple of times to show the user the chip has the reading, however, when the chip reboots, how do i store the value in memory that will not be reset on a power cycle, :-)

Easy to explain but quite complex principles to work out, :-) seems like i might be getting ahead of myself.

Acetronics2
- 10th March 2010, 14:15
Hi, Bobbo

have a look to this program ...

It's not the glow driver ( you would be lost @ first lines ...) but a lighting system shown on RC Groups.
as processor is a 12F675 ... it will be easier.

But main pulse handling routines are in ...

Bobbo_ZA
- 10th March 2010, 15:52
Ok, wow, that code has some awesome information in it, going to be fun getting this to work.

You've also set a standard as to what my code should look like, :-) I was never very good at commenting when I did programming, am learning that its almost mandatory in the real world, :-).

Thanks a mil

Rob