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: GermanyPosts: 831 |
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 KingdomPosts: 2817 |
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: GermanyPosts: 831 |
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: AustriaPosts: 133 |
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: AustraliaPosts: 6102 |
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: GermanyPosts: 831 |
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: AustraliaPosts: 6102 |
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: AustraliaPosts: 6102 |
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! VK7JH MMedit  MMBasic Help |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6102 |
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: GermanyPosts: 831 |
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: AustraliaPosts: 935 |
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: GermanyPosts: 831 |
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: AustraliaPosts: 6102 |
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: GermanyPosts: 831 |
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...) 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: GermanyPosts: 831 |
...did anybody used the PEEK command? I get always "Incorrect expression syntax" Frank |
||||
Frank N. Furter Guru Joined: 28/05/2012 Location: GermanyPosts: 831 |
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: AustraliaPosts: 3196 |
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: GermanyPosts: 831 |
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! Frank |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3196 |
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: AustraliaPosts: 6102 |
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 |