PDA

View Full Version : I2c, srf02, 16f688 -> ultrasonic rangefinder



RussMartin
- 24th February 2011, 03:17
I'm noodling (finally) with an SRF02 ultrasonic rangefinder, communicating via I2C with a 16F688.

I've used a similar program for an IR rangefinder, but I can't get this to work.

Blinky tests: Done
SRF02 indicator: Flashes about once per second
Scope: Shows both SDA and SCL lines active about once per second
Ultrasonic output: The SRF02 is "pinging", tested with an ultrasonic receiver connected to the scope.

Everything external appears to work except getting the comparison done and/or the yellow LED to so indicate

I've tried several variations, always coming back to a straightforward adaptation of code posted by jellis00 some time ago (thread is archived).

Where have I gone wrong?



@ __config _INTOSCIO & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF & _CP_OFF & _CPD_OFF

' INPUTS:
MODE VAR PORTA.3 ' MODE jumper; default is HIGH (MODE B)
' I2C INTERFACE:
SDA VAR PORTA.5 ' Serial data
SCL VAR PORTA.4 ' Serial clockS
' OUTPUTS:
RELAY VAR PORTA.0 ' Relay driver
GLED VAR PORTC.1 ' LED status indicator, green
YLED VAR PORTC.2 ' LED status indicator, yellow
' VARIABLES:
KLIX VAR BYTE ' Generic counter variable
FAR VAR BYTE ' Analog value, MAX setting, PORTA.1
NEAR VAR BYTE ' Analog value, MIN setting, PORTA.2
RANGE0 VAR BYTE
RANGE1 VAR BYTE

DEFINE ADC_BITS 8 ' Number of bits in ADC result
DEFINE ADC_CLOCK 3 ' Set ADC clock source to RC
DEFINE ADC_SAMPLEUS 25 ' Set ADC sampling time in microseconds

ANSEL =%00000110 ' Enable ADC channels AN2-AN1
CMCON0=%00000111 ' Disable the comparators
OSCCON=%01100000 ' Configure oscillator 4MHz ($60)
TRISA =%00001110 ' Set ports A3-A2-A1 as inputs
TRISC =%00000000 ' Set all ports C as outputs

RELAY=0 : KLIX=0 ' Set relay LOW and clear counter value
GLED=0 : YLED=0 ' Set LEDs to OFF

IF MODE=0 THEN ' Wait 5 seconds to stabilize detector
FOR KLIX=1 TO 5 ' During this time:
GLED=1 : PAUSE 500 ' Show MODE A by flashing green
GLED=0 : PAUSE 500
NEXT KLIX ' or
ELSE
FOR KLIX=1 TO 5 ' Show MODE B by flashing yellow
YLED=1 : PAUSE 500
YLED=0 : PAUSE 500
NEXT KLIX
ENDIF

GLED=1 ' Set green LED ON for "Ready"
' DETECTOR
MAIN: I2CWRITE SDA,SCL,$E0,0,[80] ' Request range in inches
PAUSE 100 ' Wait for ranging to finish
I2CREAD SDA,SCL,$E0,2,[RANGE1,RANGE0] ' Read range
ADCIN 2,FAR ' Get the maximum setting
ADCIN 1,NEAR ' Get the minimum ("window") setting
IF ( RANGE0 < FAR AND RANGE0 > NEAR ) THEN
GLED=0 : YLED=1
ELSE
GLED=1 : YLED=0
ENDIF
PAUSE 1000
GOTO MAIN

END

aratti
- 24th February 2011, 05:32
Code seems OK, perhaps too short the delay between the write I2C command and the read

Did you place the pullup resistors on the SDA and SCL lines?

Cheers

Al.

RussMartin
- 24th February 2011, 06:11
Thanks, Al.


Code seems OK, perhaps too short the delay between the write I2C command and the read.

It's the same delay used by jellis00, but I think he was running 18F devices and I don't know at what speed. (Or if that would make a difference.)


Did you place the pullup resistors on the SDA and SCL lines?

Yes; per the SRF02 specifications recommendation, I used 1.8K (see the schematic).

Russ

aratti
- 24th February 2011, 06:34
Russ, I think your problem is in the this line of code:

SCL VAR PORTA.4 ' Serial clockS

PortA.4 is an open collector pin and I think not suitable for I2C comm.

Try to change pin.

Cheers

Al.

FinchPJ
- 24th February 2011, 07:06
IF ( RANGE0 < FAR AND RANGE0 > NEAR ) THEN

[/code]

PBP evaluates expressions progressively - try using parentheses:
IF ((RANGE0 < FAR) AND (RANGE0 > NEAR)) THEN
I am assuming FAR is actually greater than NEAR not vice versa?
Peter

RussMartin
- 24th February 2011, 07:56
Peter, thanks for chiming in. I added the parentheses. Still nothing, but it's a good point nevertheless.

Yes, FAR is greater than NEAR. In fact, the way I have the pots configured, NEAR can never be greater than FAR.

I just checked again; during the 5-second "blinky" phase, the SRF02 is quiescent. It then responds by pinging on command (I can "see" the ping with an ultrasonic receiver and a scope--and it's appearing about once a second, as it should).

Al, is there an error in the 16F688 manual? I'm looking at Table 1-1 (page 6) and it shows A4 as TTL in, CMOS out. (In fact, I can't find an OC legend anywhere on the chart!)

I'm fairly convinced the problem is somewhere in how I'm manipulating the data, or perhaps I have misdefined something.

Bruce
- 24th February 2011, 13:27
You want to write directly to ADCON1 so you have at least Fosc/8 for 4MHz.

ADCIN doesn't do this for you - so your AD conversion clock is way too fast with ADCON1 = 0 by default.

RussMartin
- 24th February 2011, 19:12
You want to write directly to ADCON1 so you have at least Fosc/8 for 4MHz.

ADCIN doesn't do this for you - so your AD conversion clock is way too fast with ADCON1 = 0 by default.

Thanks, Bruce.

I've used ADC with other devices (12F683; 16F88; 16F1827) and always gotten by with the RC clock.

Can I use DEFINE ADC_CLOCK 1? Or if I use ADCON1=%00010000, do I simply omit the DEFINE?

Bruce
- 24th February 2011, 19:44
Hi Russ,

DEFINE ADC_CLOCK xx only works if the clock select bits are in ADCON0, so just write directly to ADCON1 to set the conversion clock. ADCON1 = %00110000 for RC, ADCON1 = %00010000 for Fosc/8 (recommended).

RussMartin
- 24th February 2011, 23:15
Thanks, everyone, for the suggestions.

After a different diagnostic strategy, I discovered I had made a really dumb mistake.

I accidentally swapped (from a working scrap of code a few days ago on a different sensor device) my ADCIN channels. In the code I originally attached,

ADCIN 2,FAR
ADCIN 1,NEAR

should have been

ADCIN 1,FAR
ADCIN 2,NEAR

My apologies to all, but still, THANKS!