I am attempting to read a PING Ultrasonic sensor through an MCP23017 I/O Expander. I knew this would be a learning experience, and it definitely has been so far. I am learning how to use some of the more advanced features of the MCP23017, such as interrupts.
So far, I can start the PING detection sequence, but this is the easy part and only requires toggling a port bit a few times.
Right now, I am trying to get the MCP23017 to interrupt the Atom PRO on IRQ1 (P8 of the Atom PRO). I believe I have the MCP23017 initialized correctly for an interrupt on change of bit 0 of Port B. The part I am very unsure of is how to get the interrupt from the chip to interrupt the Atom PRO.
Below is the current code I have.
[code]PING con p15 ’ PING Ultrasonic Ranger I/O pin
PING_Trigger con 5 ’ Trigger pulse length in uS
PING_Threshld con 25 ’ PING detection threshold
’
’ PING Ultrasonic Sonar Ranger
’
PING_I2C var byte ’ For I2C Reads
PING_Count var long ’ For counting loops until pin changes
PING_Detected var bit ’ 1 = Detected, 0 = Nothing detected
PING_Distance var word ’ PING object detection distance
PING_Echo var word ’ PING echo duration
PING_Scale var long ’ Divisor for distance units conversion
I2C_Status var word
’ Write a byte to a device on the I2C bus
dev var byte ’ Device Address/Control Byte
reg var byte ’ Register to write
dat var word ’ Data to write (8 or 16 bits)
writetype var byte ’ Write Type (Mode16 or Mode8)
I2C_Write [dev, reg, dat, writetype]
if (writetype = Mode16) then
i2cout I2C_SDA, I2C_SCL, FailedWr, dev, reg, [dat.lowbyte, dat.highbyte]
else
i2cout I2C_SDA, I2C_SCL, FailedWr, dev, reg, [dat]
endif
goto WriteDone
FailedWr:
return $FF
WriteDone:
return $00
’ Read a single byte from an I2C device register
I2C_Read [dev, reg, dat]
’ if (writetype = Mode16) then
i2cin I2C_SDA, I2C_SCL, FailedRd, dev, reg, [dat.lowbyte]
’ else
’ i2cin I2C_SDA, I2C_SCL, Failed, dev, reg, [dat]
’ endif
goto ReadDone
FailedRd:
return $FF
ReadDone:
return $00
’ Check the PING Ultrasonic Sonar Ranger
result var word
Read_PING_I2C:
PING_I2C = 0
PING_Echo = 0
PING_Count = 0
oninterrupt IRQ1INT, PING_Int
gosub I2C_Write [MCP0_DevWr, gpintenb, %00000001, Mode8] ' Enable bit 0 for interrupt on change
' Start the PING detection cycle
gosub I2C_Write [MCP0_DevWr, gpiob, %0, Mode8]
' Send the PING sensor pulse
gosub I2C_Write [MCP0_DevWr, gpiob, %1, Mode8]
pauseus 5
gosub I2C_Write [MCP0_DevWr, gpiob, %0, Mode8]
gosub I2C_Write [MCP0_DevWr, iodirb, %00000001, Mode8] ' Set bit 0 to input
enable IRQ1INT ' Enable IRQ1INT
serout S_OUT, I9600, "PING: Starting timing loop", 13]
while 1
pauseus 1
PING_Echo = PING_Echo + 1
wend
serout S_OUT, I9600, "PING: Exited timing loop", 13]
gosub I2C_Write [MCP0_DevWr, gpintenb, %00000000, Mode8] ' Disable the interrupt
' Create the divisor for cm distance conversion
PING_Scale.highword = 0
PING_Scale.lowword = 2251 ' 0.03434 * 65535 cm conversion factor
result = PING_Echo */ PING_Scale
PING_Distance = result / 2
’ PING_Distance = PING_Distance ** 1
goto PING_Done
PING_Int:
serout S_OUT, I9600, "Interrupted, PING Echo = ", DEC Ping_Echo, ", PING_I2C = ", BIN PING_I2C, ", I2C_Status = ", HEX I2C_Status , 13]
resume
PING_Done:
disable IRQ1INT
return PING_Distance[/code]
This is my first try at using interrupts, so I am sure I probably am not setting the Atom PRO up correctly, even though I believe I have it setup as the manual shows.
8-Dale