Raspberry Pi And PICAXE using i2c

PhilTheFish

New Member
Hi all

I am new to this to excuse my lack of knowledge.
I have a PICAXE 20x2 which I have set to count pulses and store the value in the Scratchpad via put 1,b1 command.
I have set the PICAXE as an i2c slave and set the Raspberry Pi to connect to the i2c bus
I can see the PICAXE on the bus by using the i2cdetect -y 1 from the RPi.
The PIC is set to address 0x50

I can read values from the scratchpad by using the following RPi command

value=i2c.read_byte_data(0x50,0x01)

This reads the value of scratchpad location 0x01 and stores it in a variable called value.
the read only seems to work if I do the following code first

i2c.write_byte_data(0x50,0x00,0x00)
If i don't do this first then the value I read back is zero and not my count value.

I then tried to write a value to the scratchpad using the following RPi Command

i2c.write_byte_data(0x50,0x01,0x33)

This should write the value of 0x33 to location 0x01 in the scratchpad.
Here lies the problem.
It does not seem to write anything.
When I check the hi2cflag which should be set to 1 when a write event has taken place it is still set to 0.
Not sure i am doing this right and do not have any idea what I have done wrong.

Sorry if all this does not make any sense
Is there anyone out there that has had any experience of this.
any help would be useful

Many Thanks

Phil
 

PaulRB

Senior Member
Phil,

Show us your picaxe code, especially the "hi2csetup" command.

When using those RPi commands (Python?), do they automatically set the lsb to 1 for write commands, or does your code need to do that
(i.e. 0x50 for read, 0x51 for write)?

Paul
 

PhilTheFish

New Member
Hi

Not Sure What Happened.
Thought I had posted my code but it Disappeared.

I'll try again here goes

This is the code that sits in my 20x2 PICAXE
Code:
init: hi2csetup i2cslave, %10100000
b1=1 'initial setup
b2=2
b3=3
b4=4
main:
put 1,b1 'put value of b1 into scratchpad location 1 
put 2,b2 'put value of b2 into scratchpad location 2
put 3,b3 'etc
put 4,b4
high 0    'flash and led to let me know its scanning
pause 1000    'wait
low 0
pause 1000
b1=b1+1    'increment value
b2=b2+1
b3=b3+1
B4=b4+1
debug
get 0,b0    'get value sent from Raspberry Pi and put in b0
goto main
I then have the following Python Code that I run from my Raspberry Pi LX Terminal

Code:
#
# Basic example of using Python-SMBus and a PICAXE 20x2
# Use at your own risk.
#
#  1 Write 0x55 to device
#  2 Check for I/O error (no device connected)
#  3 Read the device
#  4 Display result
#
# Assumes PICAXE at I2C address 0x50 (see i2c_addr)
#   Nothing connected to PICAXE that will cause problems
#
#   This version requires Python V2.6+
#      Not Python 3
#
# PC Services PICAXE/Python-smbus example
# November 2012

# define I2C address of PICAXE
i2c_addr = 0x50

# import libraries
import smbus as smbus

#configure I2C bus for functions
i2c = smbus.SMBus(1)

# value to send
temp = 0x55

#Scratchpad Location
cmd0=0x00
cmd1=0x01
cmd2=0x02
cmd3=0x03
cmd4=0x04

# Send to PICAXE
try :
   print 'PICAXE at address 0x{0:2x} Scratchpad Location 0x{1:2x} WRITE value 0x{2:2x}'.format( i2c_addr, cmd0, temp )
   i2c.write_byte_data( i2c_addr, cmd0, temp )    #Write value 0x55 to Scratchpad Location 0x00
except IOError :
   print 'PICAXE Device not found at I2C address 0x{0:2x}'.format( i2c_addr )
   error = 1
else :
   # Now read from PICAXE
   temp1 = i2c.read_byte_data( i2c_addr,cmd0 )    #Read Back Value written from above
   temp2 = i2c.read_byte_data( i2c_addr,cmd1 )    #Read value written by PICAXE
   temp3 = i2c.read_byte_data( i2c_addr,cmd2 )    #Read value written by PICAXE
   temp4 = i2c.read_byte_data( i2c_addr,cmd3 )    #Read value written by PICAXE
   temp5 = i2c.read_byte_data( i2c_addr,cmd4 )    #Read value written by PICAXE
   print 'PICAXE at address 0x{0:2x} Scratchpad Location 0x{1:2x} READ 0x{2:2x}'.format( i2c_addr, cmd0, temp1 )
   print 'PICAXE at address 0x{0:2x} Scratchpad Location 0x{1:2x} READ 0x{2:2x}'.format( i2c_addr, cmd1, temp2 )
   print 'PICAXE at address 0x{0:2x} Scratchpad Location 0x{1:2x} READ 0x{2:2x}'.format( i2c_addr, cmd2, temp3 )
   print 'PICAXE at address 0x{0:2x} Scratchpad Location 0x{1:2x} READ 0x{2:2x}'.format( i2c_addr, cmd3, temp4 )
   print 'PICAXE at address 0x{0:2x} Scratchpad Location 0x{1:2x} READ 0x{2:2x}'.format( i2c_addr, cmd4, temp5 )
This code should send the value of 0x55 to scratchpad location 0x00 and read the values incremented in b1,b2,b3,b4 back from the PIC and then print to screen.
The read works OK but the write does not.
It shows a value of 0.

any Thoughts

Regards
Phil
 
Last edited by a moderator:

geoff07

Senior Member
I haven't spotted your problem but you might like to take a look at this:

www.datsi.fi.upm.es/docencia/Micro_C/i2c.pdf (gazillions of copies on the interwatsit, this was the first that came up)

which will explain about the LSB bit used to set Read or Write. You can satisfy yourself that your code does what the spec requires. It isn't really as complicated as first glance will suggest, and it is a reliable protocol if properly controlled.

p.s. when posting code it is kinder to use
square-bracket code closing-square-bracket and square-bracket /code closing-square-bracket tags before and after
thus:

Code:
this would be code
 

PaulRB

Senior Member
Phil, I can't see what the problem is. I think your address are correct in that you have used $A0 in the hi2csetup command for address $50. I suppose the read commands in the python code would not work otherwise...

Can you see the $55 value on the picaxe debug window? (Guessing not)

Have you tried any other devices on the bus, eg. an rtc?

Paul
 

PhilTheFish

New Member
Thanks for the comments and suggestions

You are right I cannot see the $55 value in the PICAXE Debug Window
I even tried using the hi2cflag to monitor if there had been a write request to the PIC.
The flag does not change. I guess this indicates that the Raspberry Pi write has been missed somewhere!!

The Python code does not seem to object to the write operation when you execute it.
It does not report any errors.

I have not tested any other devices on the i2c bus.
What do you suggest?

As for the other suggestion from Geoff (Thanks)
I have downloaded the i2c Bus datasheet.
I am not sure how you would set the read write bit as the python code seems to take care of the protocol.

The only opyions I have are:-

Write_Byte_Data(0x50,0x00,0x55)
Read_Byte_Data(0x50,0x00)

Again
Thanks for your help guys
Its certainly a big learning curve for me

Regards

Phil
 

PaulRB

Senior Member
Here's a thought. I believe the rpi runs at 3.3V. What voltage are you running the picaxe on? If its more, eg. 4.5 or 5V, which rail are the i2c pull-up resistors attached to? Can't really imagine the read commands would work if that was the problem, but can't think of anything else at the mo.

In terms of what else to try on the bus, you could try an rtc, which could be useful, as the rpi doesn't have one of its own. Or you could get another picaxe, just an 08m2 perhaps, to be the master instead of the rpi to see if you csn get that to work.
 
Last edited:

PhilTheFish

New Member
Hi Paul

am running The PIC off the same 3.3volt supply as the Pi
Using the 3.3volt pin on the GPIO Line

I thought it would be best to power them off the same power source so as not to get the 5v and 3.3v crossed.

I have been told that the Pi has its own pull up resisters built in



Phil
 

hippy

Ex-Staff (retired)
Staff member
Two thoughts -

First, have you tried reading an writing a byte addressed I2C Eeprom such as the 24LC16 ?

Second, try writing with address 0xA0 and reading from address 0xA1, for example

wrValue =0x??
i2c.write_byte_data( 0xA0, 0x00, wrValue )
rdValue = i2c.read_byte_data( 0xA1, 0x00 )

Also, start with the simplest PICAXE code ...

#Picaxe 20X2
HI2cSetup I2CSLAVE, $A0
Do : Loop
 

PhilTheFish

New Member
Thanks for the info.
I will give that a try tomorrow...

Just as a quick note I also tried the following with no success!!

I put a PIC program in The 20x2 that just sets up i2c slave of 0x50 and looped the debug window at second intervals.

Then tried the following command from the RPi LX Terminal

i2cset -y -r 1 0x50 0x01 0x22

0x50 is the PIC chip address

This should write the value 0x22 to register 0x01 in the PIC and then read it back (-r)

it just reports a read write mismatch.
This indicates to me that the write is not working as i thought it would.

If I set the reigister manually in the PIC to the same value as I am trying to write it reports back a Match !!

Regards

Phil
 

PaulRB

Senior Member
I have insomnia tonight. Not something I get often, thankfully.

Been googling your problem. Can't find any examples of anyone successfully writing to picaxe's scratchpad from an rpi. Reading from it, yes, but not writing. You seem to be breaking new ground here, or rather failing to break new ground (which is not your fault as far as I can see).
 

PhilTheFish

New Member
Had a little Success at last.:D
Not too sure what is happening but have actually written value to the PICAXE from the Rpi with the following:-

This is my simple PICAXE Code

Code:
main:
hi2csetup i2cslave, %10100000
high 0
pause 1000
low 0
pause 1000
get 0,b0
get 1,b1
get 2,b2
get 3,b3
b10=hi2cflag
debug
goto main
All this does is scan the scratchpad looking for values and flashes output 0 to let me know the thing is still alive.
also if there is a write the hi2cflag goes high and puts the value in b10

I have then used the following on the Rpi to send a value:-

sudo i2cset -y 1 0x50 0x03 0x03 0x00 i

This writes a value of 3 to b3

sudo i2cset -y 1 ox50 0x02 0x06 0x00 i

This writes a value of 6 to b2

also every time you run then command the hi2cflag is set to 1 and then back to zero

The last value (0x00) does not seem to do anything but it will not work without either this or the "i" on the end.

Maybe someone with a little more knowledge of how things are addressed may be able to help with this??
I will keep playing about with it to see if I can make more sense of it.
Many thanks for all your help
Will keep you all posted

Regards

Phil The Happy Fish.
 
Last edited:

PaulRB

Senior Member
Glad you got it working Phil.

That 5th parameter to i2cset is supposed to be one of the letters b or w for byte or word. It doesn't seem to allow writing multiple values in the same command. As to the i... the sudo command has a -i option, but you are not using -

Confused. Hope one of the experts can shed some light. I may want to hook up a picaxe to my rpi one day.
 
I've also been trying to get a 20X2 to function as an i2c slave for the Raspberry Pi. I took Hippy's suggestion, and started with a 24LC16 EEPROM. With the 24LC16 set up at i2c address 0x50, the following Pi program correctly writes (and reads back) a series of values to and from EEPROM locations 0 through 4. (I'm using the pi smbus library, so my commands are slightly different from what Phil used.)

Code:
[FONT=Courier]from smbus import SMBus[/FONT]
[FONT=Courier]import time[/FONT]

[FONT=Courier]bus = SMBus(1)       #for pi rev 2[/FONT]
[FONT=Courier]adr = 0x50[/FONT]

[FONT=Courier]for loc in range 5:[/FONT]
[FONT=Courier]    data = loc + 65[/FONT]
[FONT=Courier]    bus.write_byte_data(adr,loc,data)[/FONT]
[FONT=Courier]    time.sleep(.01)[/FONT]
[FONT=Courier]    ch = bus.read_byte_data(adr,loc)[/FONT]
[FONT=Courier]    print ch[/FONT]
When I replace the EEPROM with a 20x2 (also set up at i2c address 0x50), the pi doesn't report any error, but the values are consistently read back as 0.

The 20X2 program just sets up the i2c slave, blinks an LED on pin C.0, and then sends the contents of scratchpad locs 0 through 4 to the terminal. To avoid the possibility that the 20X2 is executing the "get" command at the same time the pi is writing to or reading from the i2c bus, I run the pi program during the beginning of the 5 second delay in the 20X2 program.

The following 20X2 code confirms the pi output - the 5 scratchpad locations always contain 0, so the pi doesn't seem to be writing the i2c data at all.

Code:
[FONT=Courier]hi2csetup i2cslave, %10100000[/FONT]

[FONT=Courier]do[/FONT]
[FONT=Courier]  high C.0[/FONT]
[FONT=Courier]  pause 250[/FONT]
[FONT=Courier]  low C.0[/FONT]
[FONT=Courier]  wait 5 'pi writes data at this point[/FONT]
[FONT=Courier]  get 0,b0,b1,b2,b3,b4[/FONT]
[FONT=Courier]  sertxd (#b0,#b1,#b2,#b3,#b4,cr,lf)[/FONT]
[FONT=Courier]loop[/FONT]
If anyone can see where I'm going wrong, I would really appreciate the help!

Thanks… Ron
 

Technical

Technical Support
Staff member
Can you post a logic analyser trace of the i2c bus?

It could be that the Pi is sending data too fast - what is the clock frequenec of the i2c bus?
Have you tried using another PICAXE in the place of the PI to send i2c data as a test?
 
The Pi i2c bus is running at 100k - here's a snapshot of a logic analyzer trace (pi sent value of 65):

i2cshot1000.jpg

I just set up two 20X2's, and used the code example in Section 2 of the Manual. It works fine, so I'm assuming there's some sort of compatibility problem between the Pi and the 20X2. I'll need to delve into the details of the i2c protocol before I can fully understand the analyzer output - do you see anything that's obviously a problem?

Edit: I just realized that I forgot to mention that the Pi and the 20X2 are running at 3V3. Is that possibly a problem for i2c?

Thanks... Ron
 
Last edited:

PaulRB

Senior Member
Ron, its not simply a level issue, is it? Picaxe is running at 3.3V? You must have thought of that, but just in case...
 

Technical

Technical Support
Staff member
3V3 is fine. Try speeding up the PICAXE by a setfreq, as 100kHz is right on the the boundary of the i2c spec and quite fast for the default 8MHz operating speed of a 20X2. Also try sending the bytes one at a time from the PI instead of all together to generate some breathing space e.g.

bus.write_byte_data(adr)
bus.write_byte_data(loc)
bus.write_byte_data(data)
 
That Python command requires three parameters, so I can't break it up like that. However, speeding up the 20X2 did the trick!

At 16MHz, everything works as expected - either the Pi or the 20X2 can update the scratchpad, and both of them can correctly read the newly updated info. I've been struggling with this one or a while (mostly Pi configuration stuff, which is all new to me), so it's great to have it working - many thanks!

I do still have one question: I know it's an extremely remote possibility, but is there a potential problem if both processors try to access a specific scratchpad location at the same time? In other words, would it be advisable to include an additional 20X2 output line as a "busy/available" signal to the Pi?

Thanks again for your help!

Ron
 

PaulRB

Senior Member
Ron, can you use a bit or byte of the scratchpad as a "picaxe busy" indicator? And another as a "pi busy". Each would set their flag before accessing the other scratchpad data and clear it again afterwards.
 

Technical

Technical Support
Staff member
if both processors try to access a specific scratchpad location at the same time?
No real issue as long as they are not trying to write the same byte. The standard approach to that is to write/read different bytes - PI writes to address 0, PICAXE to 1. They can both read each others.
 
Thanks technical - that's good to know.

I can't think of any reason I would want both processors to write to the same byte, so hopefully I won't run into any major problems - (famous last words)!

Ron
 

Buzby

Senior Member
Is it actually possible for the two devices to access the same scratchpad location simultaneously ?

As I understand it, the scratchpad is only accessed by the PICAXE firmware. The external device writes to the hardware I2C register, then the PICAXE takes it from there and writes it to the RAM. The external device is not actually writing or reading directly to the RAM, it is mediated by the firmware.

This prevents crashes at the 'byte level', but if you need a block of values to be stable before a read or write, then you will need some kind of handshake.

Is my understanding correct ?

Cheers,

Buzby
 
Top