Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:39 29 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Help needed for I2C-slave command

     Page 1 of 2    
Author Message
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 03:11am 05 May 2014
Copy link to clipboard 
Print this post

Hi,

I try to connect my Maximite with my Micromite over I2C to translate SPI-Commands, but with no success...

I have following testcode on my µMite running:

Option AUTORUN ON

Clear

'*** Array Declaration ***

Dim I2C_buf(5)

'*** I2C Initialisation ***

I2C SLAVE OPEN &H56, 0, 0, WriteD, ReadD ' slave's address is 56 (hex)

Do
Loop


ReadD: ' received a message
I2C SLAVE READ 5, I2C_buf(0), rcvd
Print rcvd
Print "#";Hex$(I2C_buf(0));"#";Hex$(I2C_buf(1));"#";Hex$(I2C_buf(2 ));
Print "#";Hex$(I2C_buf(3));"#";Hex$(I2C_buf(4))
IReturn

WriteD: ' request from the master
I2C SLAVE WRITE 3, 0,1,2
IReturn



...and this testcode on Maximite:


'*** I2C Configuration ***

Dim I2CByte(4)
uMite_addr = &h56 ' MicroMite slave baseaddress
I2CEN 100, 100 ' Enable I2C

Do
I2CSEND uMite_addr, 0, 5, 1,3,5,7,9
Pause 1000
Loop




I expect a 5 for rcvd and #1#3#5#7#9 as output but I get most times:
5
#0#0#5#7#9

or
3
#1#3#5#5#7
2
#7#9#5#5#7
3
#1#3#5#5#7
2
#7#9#5#5#7
3
#1#3#5#5#7
2
#7#9#5#5#7
3
#1#3#5#5#7


What's going wrong? Where is the failing in my understanding?

THANKS!

Frank
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2817
Posted: 03:45am 05 May 2014
Copy link to clipboard 
Print this post

Please confirm you have any necessary pull-up resistors!

For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 05:47am 05 May 2014
Copy link to clipboard 
Print this post

Hi Phil,

there are 4.7K resistors on CLK and SDA (it's a Duinomite with internal resistors but with MMBasic on it (https://www.olimex.com/Products/Duino/Duinomite/DUINOMITE-M EGA/resources/DUINOMITE-MEGA-REV-C.pdf).

I have a realtime clock on the same bus without any problems ...

Frank
 
PicFan
Senior Member

Joined: 18/03/2014
Location: Austria
Posts: 133
Posted: 12:44pm 05 May 2014
Copy link to clipboard 
Print this post

Hi Frank !

Please, test the following lines.



ReadD: ' received a message

do while (rcvd <> 5)

I2C SLAVE READ 5, I2C_buf(0), rcvd
REM check time out

loop

Print . . .



Wolfgang
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 07:12pm 05 May 2014
Copy link to clipboard 
Print this post

I agree that there seems to be a problem but I haven't been able to pin it down yet.

I added a routine to clear the receive array at the beginning of the receive routine.
This also acts as a slight delay which seems to be required.
ReadD:
' received a message
for n = 0 to 4
I2C_buf(n) = 0
next n
I2C SLAVE READ 5, I2C_buf(0), rcvd
Print rcvd
Print "#";Hex$(I2C_buf(0));"#";Hex$(I2C_buf(1));"#";Hex$(I2C_buf(2 ));
Print "#";Hex$(I2C_buf(3));"#";Hex$(I2C_buf(4))
IReturn


The receive routing is triggered twice for each set of data sent.
Increase the pause in the sending program from 1000 to 5000 to see this.

If you change the data values being sent you may also see 'old data' appear in the receive program, even with the code to clear the array before each read.

I hope to get back into testing later today.

Jim
VK7JH
MMedit   MMBasic Help
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 07:27pm 05 May 2014
Copy link to clipboard 
Print this post

Hi Wolfgang,

I tried your code and I get always:
5
#1#3#5#7#0

- no #9

But when I change the dimension from I2C_buf to Dim I2C_buf(6) I get:
5
#3#5#7#9#1

or
5
#5#7#9#1#1

or
5
#5#7#9#1#0


Is there maybe a problem with the array???


Hi Jim,

thanks for your confirmation that something is going wrong!


Frank



 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 08:32pm 05 May 2014
Copy link to clipboard 
Print this post

More results:

Sending program (Colour Maximite)
'*** I2C Configuration ***
i2cdis

Dim I2CByte(5)
uMite_addr = &h56 ' MicroMite slave baseaddress
I2CEN 100, 1000 ' Enable I2C

Do
currentTime$=Time$
I2CByte(0)=val(mid$(currentTime$,1,2))
I2CByte(1)=val(mid$(currentTime$,4,2))
I2CByte(2)=val(mid$(currentTime$,7,2))
I2CByte(3)=(I2CByte(3)+1) mod 255
I2CByte(4)= 255-I2CByte(3)
I2CSEND uMite_addr, 0, 5, I2CByte(0)
print I2CByte(0);":";I2CByte(1);":";I2CByte(2);" #";
print hex$(I2CByte(3));"+";hex$(I2CByte(4));" (";mm.i2c;")"

Pause 5000
Loop


Receiving program on microMite
Dim I2C_buf(5)
i2c slave close
I2C SLAVE OPEN &H56, 0, 0, WriteD, ReadD ' slave's address is 56 (hex)
Do
pause 10
Loop
end

ReadD:
' received a message
for n = 0 to 4:I2C_buf(n) = 0:next n ' clears array and acts as a delay

I2C SLAVE READ 5, I2C_buf(0), rcvd
Print rcvd
Print I2C_buf(0);":";I2C_buf(1);":";I2C_buf(2);" #";
Print Hex$(I2C_buf(3));"+";Hex$(I2C_buf(4));" (";MM.I2C;")"
IReturn

WriteD: ' request from the master
I2C SLAVE WRITE 3, 0,1,2
IReturn


This sends the current time and a counter to the micromite.

Try stopping the receiver program for a while and then restart.
I end up with apparent garbage for a while. I think there is a receive buffer that is not getting reset.

We also have the second set of data but that should be easy to code around.
Without the delay in the beginning of the receive routine, errors occur.

Jim
VK7JH
MMedit   MMBasic Help
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 12:11pm 06 May 2014
Copy link to clipboard 
Print this post

More testing.
If you keep the interrupt routine short and do the main work in the main loop, the second interrupt is ignored. This gets rid of the zero byte read problem.

If you clear the micromite fully by shorting the console OI pins during start-up, the program starts receiving the I2C data correctly.
If the program is stopped and then restarted shortly after, the received I2C data is not correct. The data pointers for the receive buffer are out of step.

The error does seem to correct itself 'eventually'

New program for the micromite (slave)

clear
Dim I2C_buf(5)
i2c slave close
I2C SLAVE OPEN &H56, 0, 0, WriteD, ReadD ' slave's address is 56 (hex)

Do
if datahere = 1 then
datahere=0
for n = 0 to 4:I2C_buf(n) = 0:next n ' clears array and acts as a delay
I2C SLAVE READ 5, I2C_buf(0), rcvd
Print rcvd
Print I2C_buf(0);":";I2C_buf(1);":";I2C_buf(2);" #";
Print Hex$(I2C_buf(3));"+";Hex$(I2C_buf(4));" (";MM.I2C;")"
endif
if inkey$=chr$(27) then exit do
Loop
i2c slave close
end

ReadD:
' received a message
datahere=1
IReturn

WriteD: ' request from the master
I2C SLAVE WRITE 3, 0,1,2
IReturn


Jim

Edit:
My current test looks like it is receiving correctly but is actually 8 readings behind!
Edited by TassyJim 2014-05-07
VK7JH
MMedit   MMBasic Help
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 01:40pm 06 May 2014
Copy link to clipboard 
Print this post

More progress.
Here we read up to 25 bytes from the I2C buffer instead of the required 5 bytes.
Keep reading until the buffer is nearly empty and the check for the correct size (5 bytes) before using the data.

This will eventually clear the buffer and get the sending and receiving streams into sync.

I also think that simply powering the micromite down without doing a full reset will reset the buffer.

clear
Dim I2C_buf(25)
i2c slave close
I2C SLAVE OPEN &H56, 0, 0, WriteD, ReadD ' slave's address is 56 (hex)

Do
if datahere = 1 then
datahere=0
for n = 0 to 4:I2C_buf(n) = 0:next n ' clears array and acts as a delay
do
I2C SLAVE READ 25, I2C_buf(0), rcvd ' try to read a lot more than expecting
Print rcvd
loop until rcvd <= 5 ' discard until the buffer is empty
if rcvd = 5 then ' finally we have a good reading to use
Print I2C_buf(0);":";I2C_buf(1);":";I2C_buf(2);" #";
Print Hex$(I2C_buf(3));"+";Hex$(I2C_buf(4));" (";MM.I2C;")"
endif
endif
if inkey$=chr$(27) then exit do
Loop
i2c slave close
end

ReadD:
' received a message
datahere=1
IReturn

WriteD: ' request from the master
I2C SLAVE WRITE 3, 0,1,2
IReturn


I think we still need a bit of a delay between the interrupt and reading the data to allow for the full number of bytes to arrive.

Jim

VK7JH
MMedit   MMBasic Help
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 08:06pm 07 May 2014
Copy link to clipboard 
Print this post

Hi Jim,

thanks a lot for your tests!
But I am still not sure what I must do to transfer my Bytes to my MicroMite

@Geoff:
Is the buffer correct handled in the I2Cslave command? Can you tell me how to transfer five Bytes from Maximite to MicroMite?

The I2Cslave functionality is very important for my current project! I have to send Bytes over I2C to µMite and then send it via SPI to a three motor stepper control.
The controlling of the steppers works very well but I fail on the I2C transmission...

Should I send the Bytes within the "ReadD:" routine via SPI or in the MAIN? How can I tell the master that the µMite is busy in that time?

THANKS

Frank
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 08:54pm 07 May 2014
Copy link to clipboard 
Print this post

Frank
Have you read the Micromite manual pages from bottom paragraph on page 61 to end page 64? If not then there may be something there for you.
Bob
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 09:50pm 07 May 2014
Copy link to clipboard 
Print this post

Hi Bob,

of course I have read these pages - my code based on it!
But I don't get a stable transfer between µMite and Maxiximite as TassyJim confirm. "delay between the interrupt and reading" and "powering the micromite down" to reset the buffer seems to me as a failure of the I2Cslave command...

All of my efforts are unsatisfying! It's gamble to transfer the correct data to the µMite...

Did you have experience with the I2Cslave function???

Frank
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 10:23pm 07 May 2014
Copy link to clipboard 
Print this post

Frank,
I still need to find time to do some more experimenting.
This is my understanding so far:

The I2C receive happens in the background once it is started.
There is a 255 byte buffer which holds the incoming data until your program retrieves it with a read.
The micromite has no idea how many bytes are coming, there are just added unto the end of the buffer.
It is very much like the RS232 receive buffers.
As soon as one byte of data is received, the interrupt occurs. If you are expecting a number of bytes, you have to allow sufficient time for the full number of bytes to arrive.
If you only fetch the exact number of bytes you are expecting, any extra data will stay in the receive buffer and be sent to your program the next time you do a read.
It is safer to try and read a large number of bytes and see what you are given. If you are given the number of bytes you are expecting, the data is 'probably' valid.
If there is more than you expected, the last x bytes 'should' be the most recent data.

If it was my program, I would be including some sort of checksum to be confident that the data is OK.

I think that there is a bug in the receive routines:
It looks like the background receive continues even after the I2C SLAVE CLOSE command is issued.

This is the first time I have played with I2C SLAVE mode so forgive the muddled explanations.

Jim



VK7JH
MMedit   MMBasic Help
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 11:00pm 07 May 2014
Copy link to clipboard 
Print this post

Hi Jim,

thank you very much for your explanation! That helps me very much!

Did you think there would be any possibility to clear the buffer with a POKE? (...powering the micromite down for buffer cleaning is no option for me...)

  Quote  If it was my program, I would be including some sort of checksum to be confident that the data is OK.

Yes, I think I must implement any sort of check...

I2C SLAVE is uncharted waters for me too. I have only experience with master functions...

Frank
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 12:56am 08 May 2014
Copy link to clipboard 
Print this post

...did anybody used the PEEK command? I get always "Incorrect expression syntax"

Frank
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 01:15am 08 May 2014
Copy link to clipboard 
Print this post

Hi Jim,

it seems that a simple "I2C SLAVE CLOSE" before opening the I2C port clear the buffer!
I get still my data twice but all and in correct order!

Can you confirm that?

Frank
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3196
Posted: 01:34am 08 May 2014
Copy link to clipboard 
Print this post

Unfortunately I do not have the time to delve into this in detail (nor will I for the next few months). I have checked the code and I2C SLAVE CLOSE definitely stops the I2C hardware and therefore no more data could be received. Perhaps the data is still sitting in the I2C hardware buffers, something to be investigated.

The I2C SLAVE CLOSE command returns the memory used for the input buffer to the general memory pool. If you then issued a I2C SLAVE OPEN command the memory would be re allocated to the buffer and zeroed. So yes, a I2C SLAVE CLOSE followed by a I2C SLAVE OPEN would clear the buffer.

Geoff
Geoff Graham - http://geoffg.net
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 831
Posted: 01:52am 08 May 2014
Copy link to clipboard 
Print this post

Hi Geoff,

thank you very much for your reply!
It seems that something is wrong with the pointer of the buffer or with the buffer itself???

Ok, I get the correct five Bytes when I close the I2C slave at the beginning of my program.
But than I read anytime the same first five values from the buffer, independent what I send from the master!
A new CLOSE and SLAVE OPEN (at the end of the ReadD: routine) has no effect - always the first five Bytes are appearing (2x) ...

Did you have any another idea?

THANKS!

FrankEdited by Frank N. Furter 2014-05-09
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3196
Posted: 02:32am 08 May 2014
Copy link to clipboard 
Print this post

I don't understand this. There could be a bug in the I2C routines but it just does not seem likely - I did a lot of testing and experimenting with the slave function while I was developing the code in the manual and it does work.

The problem is that I just do not have the time to analyse your code (I am leaving for overseas in a couple of weeks).

Could you start with the exact program as in the user manual and verify that it does work? Then, you could add your own special features and see where it starts to give trouble.

Geoff


Geoff Graham - http://geoffg.net
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 04:45pm 08 May 2014
Copy link to clipboard 
Print this post

Geoff,
Most of the time, code such as the example in the user manual will work OK.

If you stop the slave with ctrl+C without issuing the I2C SLAVE CLOSE, the master does not receive an error. MM.I2C = 0.
If you do issue the I2C SLAVE CLOSE command, the master will correctly see an error. MM.I2C = 1.

If you stop the slave from listening with I2C SLAVE CLOSE and then restart listening with I2C SLAVE OPEN, there is 'garbage' in the slave buffer.
This will happen even if you stop the master, pause the slave listening, restart listening and then restart the master. The buffer gets out of step without any I2C activity on the bus.

I have used strings instead of arrays to make it easier to see what's happening (I hope).

Both programs are for the microMite:
Master:
'*** I2C Master ***

uMite_addr = &h56 ' MicroMite slave baseaddress
I2C open 100, 1000 ' Enable I2C

do
for n = asc("A") to ASC("Z")
info$=string$(5,chr$(n))
I2C write uMite_addr, 0, 5, info$
print info$;" (";MM.I2C;")"

Pause 5000
next n
loop


Slave:
clear
i2c slave close
mainLoop:
I2C SLAVE OPEN &H56, 0, 0, WriteD, ReadD ' slave's address is 56 (hex)
print "Slave listening, press 'esc' to stop"
Do
if datahere = 1 then
datahere=0
I2C SLAVE READ 255, info$, rcvd ' try to read a lot more than expecting
Print rcvd, len(info$),info$
endif
if inkey$=chr$(27) then exit do
Loop
i2c slave close
print "Slave stopped, press C to continue"
do
if inkey$="C" or inkey$="c" then exit do
loop
goto mainLoop

end

ReadD:
' received a message
datahere=1
IReturn

WriteD: ' request from the master
I2C SLAVE WRITE 3, 0,1,2
IReturn


I can not see anything in the C code that would cause this behavior, but my C is not good, and the I2C interrupt routine hurts my brain just looking at it!

Do I2C_Rcv_Tail and I2C_Rcv_Head have fixed addresses we can PEEK at?

Jim


VK7JH
MMedit   MMBasic Help
 
     Page 1 of 2    
Print this page
© JAQ Software 2024