Page 1 of 1

SPI py2py Master and Slave comm problem

Posted: Wed Sep 27, 2017 3:33 pm
by Adixylian
So I got two pyboards MicroPython v1.9.1-196-g45645043 on 2017-07-29; PYBv1.1 with STM32F405RG communicating with each other via SPI
One pyboard acts as a Slave, the other one as a master

The problem is, the communication works for some short period of time and then something breaks and the comms go nuts.

Master code:
`py2=pyb.SPI(2, pyb.SPI.MASTER, 500000, polarity=0, phase=1, bits=8, firstbit=pyb.SPI.MSB, ti=False, crc=0x7)

ss=pyb.Pin('Y5', pyb.Pin.OUT_PP)
ss.high()

def py2py():
ss.low()
pyb.delay(5)
data=py2.send_recv(b'\x00\xaa\x00\xbb\x00\xaa\x00\xbb\x00\xaa\x00\xbb\x00\xaa\x00\xbb\x00\xaa\x00\xbb\x00\xaa\x00\xbb')
ss.high()
`

Slave code:
`py1 = pyb.SPI(2, pyb.SPI.SLAVE, 500000, polarity=0, phase=1, bits=8, firstbit=pyb.SPI.MSB, ti=False, crc=0x7)
data=bytearray(24)
ss=pyb.Pin('Y5', pyb.Pin.IN)

def f(a):
py1.send_recv(data)

inter=pyb.ExtInt(ss, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_DOWN, f)
`
As you can see, the Slave pyboard uses an interrupt. So, when Master calls the function py2py(), he triggers the interrupt on the Slave who then does what it does, it sends the data.

And it works for some short period of time, then it just breaks and the Master starts receiving weird buffers. Or, if I also have comms via i2c(1) on Master, the SPI comm completely breaks and Master never receives anything --> data is data=b'\x00'*24

I'm not profesionallist for communications and it's still a new thing for me, so if somebody can help me, please do :D

What I did try is using only py2.recv and py1.send, got the same thing. And, it doesn't work without the pyb.delay() in py2py() func.

Note, the pyboards both have other comms via i2c and the other SPI pins (all the comms work perfect), but they do not use interrupts. The only interrupt that is used in the whole programs is the one that is written here.

And I know that the SPI comms, when pyboard acts as Master, works completely fine. It has been tested on one of my sensors and it works all the time as it should :D

Help me please

Re: SPI py2py Master and Slave comm problem

Posted: Mon Oct 09, 2017 6:38 am
by ajie_dirgantara
Some problem with pyboard SPI could be solved by using spi.deinit() here and there. In my case, I do deinit() everytime I need to read SPI data, and re-initialize everytime I do SPI write.

Re: SPI py2py Master and Slave comm problem

Posted: Tue Oct 10, 2017 8:27 am
by pythoncoder
I wonder if the problem is interrupt latency. I'd try a much lower baudrate to see if that has any effect.

Re: SPI py2py Master and Slave comm problem

Posted: Thu Oct 12, 2017 5:21 pm
by Adixylian
I tried many different baudrates, didn't have any effect.

Without interrupt it works every cca 10th time.
All I did is just to add if statement in the end of the Slave main loop
Something like -->
...
if ss==0:
spi.write(package,timeout=XY)
else:
print('no comms')
...

Also, I added the delay in the master and timeout on the slave , so that the slave always waits for the master

I tested the comms for few hours (I think it was on for some 4 hours), and the comms had the same "scheme" as on the beginning.
Well that is some progress because the comms didn't die after some time. But still, only every approx 10th time SPI comm is succesfull

I'm going to try adding deinit() and init() and see what will happen

Also, initializing UART comms while SPI is also init adds some problems, but I don't know why...

EDIT: I tried deinit() and because of unknown reasons, it works... SPI communication is stable and has 100% succesfull comms.

But, that is without the interrupt.
With interrupt comms are awful. But like this, I have to put delay(x), where x is the time that is needed for slave to finish it's main loop. That makes SPI comms not so helpful because the time that the delay adds is just too big...

Re: SPI py2py Master and Slave comm problem

Posted: Fri Oct 13, 2017 8:08 am
by pythoncoder
You mention UARTs. In my opinion UART communications are better supported and more reliable than SPI slave mode. Communication is asynchronous and hardware flow control is supported, so it can be pretty bomb proof. If I wanted to communicate between MicroPython targets I would use UARTs if at all possible.

As you've discovered MicroPython lacks an asynchronous buffered SPI slave mode. That said, I'm not sure why your interrupt driven code is failing when run at low baudrates.

Re: SPI py2py Master and Slave comm problem

Posted: Sat Dec 28, 2019 11:33 pm
by bradstew
Perhaps the reason interrupt don't work is the "ti=false" property.
I'm only guessing as there is no documentation on what this does

Re: SPI py2py Master and Slave comm problem

Posted: Sun Dec 29, 2019 3:48 am
by smhodge
Perhaps it doesn't work, especially *randomly* does not work, is that your code is attempting to do too much inside the ISR -- you are attempting to do a complete SPI send. Move that out of the ISR and into the main loop and simply set a flag in the ISR that the main loop reacts to. That is what I do with all ISR's that I write unless it's something ridiculously simple and fast like toggling a led or output pin. I'm not surprised you are occassionally getting bitten by not following the universal KISS rule of ISR's (not just uPython), which is well explained in the general uPython documentation -- see "Writing Interrupt Handlers" under "The Micropython Language".