I2C and the Atom PRO

Thanks! I will dig into this and see if I can find a way to do the I2C using the hardware features directly.

8-Dale

Almost. The bit sets whether the ADDRESS argument is 8 or 16bits(some eeproms use 16bit addressing and some use 8bit addressing, I’ve never seen any other i2c device use 16bit addressing). Data is always 8bits whide in i2c.

If you use google search for “h8-3664 hardware manual” without the quotes. Or you can just use the one included with the Atom software(goto the help menu). I don’t remember how long ago we added those menu options so if you have an older version of the AtomPro software you may not have it.

The fact that some of your devices are “timing sensitive” indicates they do not meet the Philips specification. The I2C communications format is a sybcronous format. That means any compatible device should work up to the max speed of the spec(100khz originally and higher on newer devices) but ALL devices should work at any speed slower than that. Thats the point of a syncronous communications system. It’s speed is whatever the controlling micro can handle upto a max speed.

Understood. Earlier I had problems with two different issues. On the RoboNova as I mentioned earlier you had to bit twiddle each bit in Basic and at first I had problems making sure the timings worked Ok, especially with the ACK and NAK…

The other problem I had was with an LCD display with an I2C interface. If you tried to output commands to it at times it would lock up and lock up and keep either SCL or SDA pulled either high or Low (been awhile so I don’t remember fully). I found the only way to clear it was to power cycle as the processor reset did not clear the bus.

Sorry Dale, this is a little off topic

Kurt

Ok well actually I’ve never heard of 8 or 16 bit addresses for I2C, the device address is typically 7 or 10 bits :wink: The point however is Dale appears to be trying to set this bit 0 to determine read or write access and I don’t think it occured to him that you had already done and re-assigned the function of the bit to your own purpose. I also went back as re-read the thread and while I see mention of adding pull-up resistors what I don’t see if the value used. Personal experience has shown this to be non-trivial in some arrangements and also that what works for 100K I2C does not work for 400K I2C. :blush: So anyway, what is the value you expect people to use for your implementation and is this the value that is being used seems like a good sort of question.

It must just be a coincidence that setting bit 0 of the control byte to 0 tells the Atom PRO to use 8 bit addressing and happens to be the same for a write to an I2C device. I sure can’t write to the MCP23017 when I set bit 0 of the control byte to 1.

I have a feeling this is really going to mess my brain up when I have to start manipulating everything manually with a different microcontroller. Sometimes, it is just not good to try doing too much for a person, as I think is the case here for me.

I do believe I now understand the difference between how the Atom PRO is doing I2C and how I would have to do things when I have to set everything up myself. I think I was trying to do things myself and it just was not working with the Atom PRO.

I do have my complete circuit working now and am getting all the results I should get. I also rewired Ports A and B of the second MCP23017 so that Port B is the MSByte and Port A is the LSByte, which makes creating LED sequences much easier. :smiley::smiley: I have both 8 bit and 16 bit modes of the MCP23017 working reliably now. :smiley:

I am now going to add my third MCP23017 onto the I2C bus and do my traffic light simulation, including main and cross traffic lights. :smiley:

I’ll post my code and circuit, if anyone is interested, after I create a schematic for the circuit. My circuit and program for this also demonstrates the very noticable difference between using the 8 bit and 16 bit write modes with the MCP23017. I have 16 LEDS connected to the second MCP23017, and do the same sequence in both 8 bit and 16 bit write modes.

Thanks to you, Kurte, and Acidtech for all the patience while my brain took its own sweet time wrapping itself around all this. :wink: I understand it all now, but it still makes my head hurt to think about it sometimes.

8-Dale

Which pins are you using for your I2C bus? P6 (SDA) and P7 (SCL) are the Atom PRO’s hardware I2C pins. I don’t know whether using the hardware I2C pins versus a different pair of pins makes any difference when using the I2CIN and I2COUT commands though.

It just goes to show you that there is more than one way to accomplish something, even if some are more painful than others.

8-Dale

I’ve been browsing through that hardware manual, and the H8 does look like a very nice microcontroller. I wish more companies would make their microcontrollers into modules we could use easy. I guess that’s where companies like Sparkfun come in, with all their header boards and such.

It would be really cool to get an H8SX based microcontroller - some of them have up to 512K of flash. :smiley: Maybe Basic Micro will come out with a Molecule Microcontroller (faster and more memory than an Atom). :smiley: I’d a 40 pin package though, to handle more I/O pins.

8-Dale

I started out with 1K pull ups, but switched to 4.7K pull ups, which I am still using.

I now have all three of my MCP23017’s on the I2C bus and am running them without a problem. :smiley: I could have run this circuit with just two of the chips, but everything is too spread out. I’m only using Port A on the first and third chips and both ports on the second chip. I have my traffic light running driven by the third chip, which includes the main and cross street lights. :smiley:

8-Dale

We’ve thought about it. Right now we’re pretty busy but after the 40pin AtomPro comes out(I’ve got the prototype sitting on my desk) We’re keeping an eye on the SX chips. Hopefully Renesas will come out with a module friendly version(eg 9mm or smaller package).

I’ll hope too! :slight_smile: To be honest, I didn’t really think too much of the Renesas microcontrollers until I started looking at the hardware manuals. The seem to be very nice, and I can see why you went with them for the Atom Pro.

I’ve been trying to get interrupts working with the Atom Pro and my MCP23017 I/O Expanders, so I had to dig in and learn how the Atom Pro does stuff internally. I still don’t grok how to use interrupts with the Atom Pro though, and have not been able to get it working on the P8/IRQ1 pin.

I am not having a good week for getting things to work. :frowning:

8-Dale

The addressing I’m talking about is the memory address of an eeprom, which was the primary focus of the i2c commands oringinally. Some eeproms use an 8bit address(handles upto 256bytes), some use 8bits plus the address bits of the control byte(which allows controlling upto 2kbytes),some use 16bits of address(upto 65k bytes) and some use 16bit addresses and control byte address bits(allowing a max of 512kbytes).

AtomPro i2c commands do no support the 10bit device addressing you mention. For those who don’t know our control byte of the i2cin and i2cout commands is the 7bit address EddieB is talking about. For eeproms the 7bit address is 1010AAA were each A can be either 0 or 1 to allow addressing upto 8 seperate eeprom i2c chips on a single i2c bus.

The pullup depends on the device and the speed, just as you said above. For 400k i2c a think 1k is mandatory. You need a hard pullup otherwise the slew rate won’t meet minimums. However the AtomPro only runs i2c at 100k so in most cases you can use a 4.7k or possibly a 10k.

Note. The i2cin and out commands have no hardware equivilent at the moment. There is i2c hardware on the AtomPro but you have to set it up and write the code to handle it from scratch. It’s not too difficult but I’ve never gotten around to writing a hi2c system. At the moment it’s kind of low on my todo list.

One of the tricker parts about these chips is Hitachi makes you switch a pin from being a standard I/O to an interrupt pin. To use the IRQ1 int you have to do an ONINTERRUPT to your int handler, ENABLE the IRQ1 int AND set bit 5(the IRQ1 bit) of the PMR1 register. Otherwise the interrupt hardware will never see the signal from the physical pin. You may also need to clear the IRQ1 interrupt flag inside your interrupt handler but I think we handle that for you(I’m not in front of my work machine so I’m not sure).

Also, just a reminder to always “resume” to exit an interrupt handler. Never “return”.

OK, to enable the interrupt, I have the following:

[code] ’ Enable the IRQ1 Interrupt
oninterrupt IRQ1INT, PING_Int

dir8 = 0													' Set the P8/IRQ1 pin to input
ieg1 = 1													' Edge polarity of Atom Interrupt
pmr1.bit5 = 1												' Set the Atom PRO's IRQ1 enable bit
enable IRQ1INT												' Enable the IRQ1INT interrupt[/code]

Is this the right sequence needed to enable an interrupt on the Atom PRO?

Here is my interrupt routine

' Interrupt Routine PING_Int: serout S_OUT, I9600, "Interrupted, PING Echo = ", DEC Ping_Echo, 13] PING_Status = 1 ' Set for an orderly exit from the timing loop pmr1.bit5 = 0 ' Clear the Atom PRO's IRQ1 interrupt bit resume
I added the pmr1.bit5 = 0 just to be sure it got done. :smiley:

As you can see, I have the ‘resume’ part down. :slight_smile:

However, I am still not getting the interrupt I want. :frowning: I have tried all manner of everything you and others have suggested, without success. :frowning:

My entire current code for trying to read the PING through the MCP23017 I/O Expander follows.

[code]’ I2C Configuration
I2C_SDA con p6 ’ I2C Data
I2C_SCL con p7 ’ I2C Clock

’ MCP23017 Hardware Setup
MCP_Reset con p12 ’ Hardware RESET, tied to all MCP23017’s pin 18

’ Microchip MCP27013 I/O Expander Configuration
MCP0_DevWr con %01000000 ’ Atom PRO 8 Bit Addressing
MCP0_DevRd con %01000001 ’ Atom PRO 16 Bit Addressing

MCP1_DevWr con %01000010
MCP1_DevRd con %01000011

MCP2_DevWr con %01000100
MCP2_DevRd con %01000101

Mode16 con 16
Mode8 con 8
'======================================================================================
’ Port A Registers (8 Bit Mode)
iodira con 0x00 ’ Direction Bit Control Reg
iobitsa con %00000000 ’ Direction Bit Settings Reg (0 = output, 1 = input)

ipola con 0x01 ’ Interrupt Polarity Control Reg
gpintena con 0x02 ’ Interrupt Enable Reg
defvala con 0x03
intcona con 0x04

iocona con 0x05 ’ I/O Configuration Reg
ioconseta con %10111000 ’ IOCON register setting

gppua con 0x06 ’ Pull-Up Control Reg
intfa con 0x07 ’ Interrupt Flag Register
intcapa con 0x08
gpioa con 0x09 ’ General Purpose I/O
olata con 0x0A ’ Output Latch Reg

’ Port B Registers (8 Bit Mode)
iodirb con 0x10 ’ Port B Direction Bit Control Address
iobitsb con %00000000 ’ Port B Direction Bit Settings (0 = output, 1 = input)

ipolb con 0x11 ’ Interrupt Polarity Control
gpintenb con 0x12 ’ Interrupt Enable Reg
defvalb con 0x13
intconb con 0x14

ioconb con 0x15 ’ I/O Configuration Reg
ioconsetb con %10111000 ’ IOCON register setting

gppub con 0x16 ’ Pull-Up Control Reg
intfb con 0x17 ’ Interrupt Flag Register
intpolb con 0x18
gpiob con 0x19 ’ General Purpose I/O Reg
olatb con 0x1A ’ Output Latch Reg

'========================================================================================

’ Port A Registers (16 Bit Mode)
iodira16 con 0x00
iodirb16 con 0x01

iocona16 con 0x0A
ioconb16 con 0x0B

gpioa16 con 0x12
gpiob16 con 0x13

olata16 con 0x14
olatb16 con 0x15

'========================================================================================


’ PING Ultrasonic Sonar Ranger

PING con p10 ’ PING Ultrasonic Ranger I/O pin
PING_Trigger con 10 ’ Trigger pulse length in 0.5 uS steps (Atom PRO)
PING_Threshld con 25 ’ PING detection threshold in cm


’ 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
PING_Result var word
PING_Status var byte

' Testing for reading a PING sensor through the MCP23017 I/O Expander
for loop = 1 to 20
	gosub Read_PING_I2C [PING], PING_Distance
	serout S_OUT, I9600, "PING Distance = ", DEC PING_Distance, " cm", 13]
next

goto Finished

’ 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)
rwtype var byte ’ Write Type (Mode16 or Mode8)
I2C_Write [dev, reg, dat, rwtype]
if (rwtype = 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, rwtype]
if (rwtype = Mode16) then
i2cin I2C_SDA, I2C_SCL, FailedRd, dev, reg, [dat.lowbyte, dat.highbyte]
else
i2cin I2C_SDA, I2C_SCL, FailedRd, dev, reg, [dat]
endif

goto ReadDone

FailedRd:
return $FF

ReadDone:
return $00

’ Check the PING Ultrasonic Sonar Ranger
PING_Pin var byte
Read_PING_I2C [PING_Pin]
serout S_OUT, I9600, “Entering PING Routine”, 13]

PING_I2C = 0
PING_Echo = 0
PING_Status = 0

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, %00000000, Mode8]

' Enable the IRQ1 Interrupt
oninterrupt IRQ1INT, PING_Int

dir8 = 0													' Set the P8/IRQ1 pin to input
ieg1 = 1													' Edge polarity of Atom Interrupt
pmr1.bit5 = 1												' Set the Atom PRO's IRQ1 enable bit
enable IRQ1INT												' Enable the IRQ1INT interrupt

serout S_OUT, I9600, "Sending PING Pulse", 13]

' Send the PING sensor pulse
gosub I2C_Write [MCP0_DevWr, gpiob, %00000001, Mode8]
pauseus 5
gosub I2C_Write [MCP0_DevWr, gpiob, %00000000, Mode8]

gosub I2C_Write [MCP0_DevWr, iodirb, %00000001, Mode8]		' Set bit 0 to input

’ gosub I2C_Read [MCP0_DevWr, gpiob, PING_I2C, Mode8]
serout S_OUT, I9600, "PING: Starting timing loop, PING_I2C = ", BIN PING_I2C , 13]

while (PING_Echo < 6000) AND (PING_Status <> 1)
	pauseus 1
	PING_Echo = PING_Echo + 1
wend

serout S_OUT, I9600, "PING: Exited timing loop, PING_Echo = ", DEC PING_Echo, 13]

gosub I2C_Write [MCP0_DevWr, gpintenb, %00000000, Mode8]	' Disable the interrupt on change

' Create the divisor for cm distance conversion
PING_Scale.highword = 0
PING_Scale.lowword = 2251			' 0.03434 * 65535 cm conversion factor

PING_Result = (PING_Echo */ PING_Scale) / 2

’ PING_Distance = result / 2
’ PING_Distance = PING_Distance ** 1

goto PING_Done

’ Interrupt Routine
PING_Int:
serout S_OUT, I9600, "Interrupted, PING Echo = ", DEC Ping_Echo, 13]
PING_Status = 1 ’ Set for an orderly exit from the timing loop
pmr1.bit5 = 0 ’ Clear the Atom PRO’s IRQ1 interrupt bit
resume

PING_Done:
disable IRQ1INT
gosub I2C_Write [MCP0_DevWr, iodirb, 0, Mode8] ’ Reset all Port B pins to outputs
return PING_Result

Finished:
end[/code]
I included my I2C_Write and I2C_Read routines, since my Read_PING_I2C routine calls them.

What am I still doing wrong?

8-Dale

I am up early with the dogs and have a couple of ideas, which since I am not fully awake may be half baked.

  1. I know you said you did not have a logic probe, but maybe hook up an LED to PIN8 such that you can maybe see if it does ever get triggered. It may be to quick to see…

  2. Try enabling the interrupt higher up in the function, even before you do your writes. Yes you may get some false interrupts, but it would be nice to see if you can actually get the interrupt code to be called.

  3. Now for the half baked idea :bulb: . Could you hook up two pins I/O extender to the I/O pin of the PING. Lets say Pin 0 of both A and B. Configure Pin A0 for Read and pin B0 for write. Setup the interrupt on Port A (would need to change which pin goes to the Pro). Then you would do your writes to B0 high and Low, which may cause the interrupt to happen, likewise another interrupt hopefully when the ping completes.

As I said it was an early morning idea…

So, does that mean using the 1K pull ups is actually better for the lower speed I2C also? I have a lot more 1K resistors here than I have 4.7K (just two I could find in my resistor grab bag). I have lots of 1K and 10K though.

Ah, OK, so I would have to write the code for the hardware I2C pins if I wanted to take full advantage of them. I was wondering about that.

8-Dale

Hi Kurte,

I do use LEDs for that purpose and it generally works quite well, except for the very high clock rate pulses. I have LEDs on the PING line and the MCP23017 I/O pin the PING is connected to. I can ping the PING just fine now. :slight_smile:

I’ve tried having the interrupt enables all over that routine, but have not tried the current setup at the very beginning. I am just interested in getting an interrupt right now.

Interesting. I had not thought to try a setup like this. I’d use pins A7 and B7. This sort of setup shouldn’t actually be necessary, but I can see why it might be useful.

I usually get some of my best ideas just after I get into bed, and then I have to fight to keep from getting up again just to try it out (and sometimes I do). :slight_smile:

8-Dale

If it were me, I would probably test wire something like one of the buttons or the like to P8 and try pressing and releasing, just to see if you can actually trigger the interrupt. Then at least you will know handler is properly set up.

Just another not very early in the morning thought…

I would do that, but my bot board is sick. The regulator broke off it. :frowning: I don’t have any push button switches to play with.

8-Dale