Read bit stream from a Serial Interface

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
giacomoalbe
Posts: 9
Joined: Thu Dec 22, 2016 10:15 pm

Read bit stream from a Serial Interface

Post by giacomoalbe » Thu Apr 20, 2017 5:04 pm

Hi all!

I'm facing a problem with serial communication with the MicroPython board.

I have a digital sensor that outputs data to a Synchronous Serial Interface (SSI) according to a protocol that's shown in the figure below:
Screen Shot 2017-04-20 at 18.53.46.png
Screen Shot 2017-04-20 at 18.53.46.png (44.31 KiB) Viewed 9147 times
As you can see from this datasheet https://ams.com/ger/content/download/43 ... _EN_v2.pdf the reading of the value is init by an high impulse on a sensor pin and after a period of time (which is written in the datasheet) the sensor starts to output values on the serial line.

Any subsequent reading of the value are init in the same way.

The problem is that this particular protocol is not coded in any MicroPython class, because it's not SPI nor UART nor I2C or any other protocol which is included with MicroPython distribution.

My question is: do I have to make a pyb module or can this task be achieved with only MicroPython?
Further more, I need to know how to give the sensor the CLK, is there any pin on the Micropython? Can I do this with Pythonor do I have to create a module?

If the C module is the only way, can you please point me some documentation on how to do this?

Thanks a lot for your precious help!

Giacomo

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: Read bit stream from a Serial Interface

Post by deshipu » Thu Apr 20, 2017 5:29 pm

This looks vaguely like I2C. You might check the details, it might be actual I2C (also called IIC or TWI), but they avoid calling it by name because there were trademark and patent issues with it.

Otherwise, you should be able to read that with the SPI peripheral.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Read bit stream from a Serial Interface

Post by Roberthh » Thu Apr 20, 2017 8:22 pm

You can create the signals CSn, CLK in Python and read also the data back, since the device has no restriction on slow reading. The clock raze that can be achieved depends on the code generator used. Using viper code, about 1 MHz could be possible.

giacomoalbe
Posts: 9
Joined: Thu Dec 22, 2016 10:15 pm

Re: Read bit stream from a Serial Interface

Post by giacomoalbe » Fri Apr 21, 2017 10:15 am

Thank you all for your precious support!

Once I get the sensor to work properly, I'll try with Python!

Maybe a stupid question: what is Viper code? It is something related with programming or is it actual coding language or paradigm?

Thanks again for your precious help!

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Read bit stream from a Serial Interface

Post by Roberthh » Fri Apr 21, 2017 10:20 am

Viper is a function decorator, which causes the python compiler of the device to use a code emitter, which generates effective native machine code. It supports a language subset only, but for bitbanging tasks thsi is very useful. Look here:
http://docs.micropython.org/en/latest/p ... ight=viper

giacomoalbe
Posts: 9
Joined: Thu Dec 22, 2016 10:15 pm

Re: Read bit stream from a Serial Interface

Post by giacomoalbe » Wed May 10, 2017 12:51 pm

Hi all again!

I tried to connect the sensor to the MicroPython and it actually works for sensing the angle.
The problem starts when I need to read speed (so differential measurements).
Right now the pyboard needs something like ~400 us to read an angle measure, and this is lower a lot the rate in which I can read speeds.

I tried to use the viper decorator, but it doesn't help much.
I think I'm doing wrong something, since I use the out pin to generate manually the clk signal and I think that there's should be a better approach (maybe using interrupts? I dunno).

This is the code I used to decode the angle from the Serial Interface.

Code: Select all

   
   @micropython.viper
    def read(self):
        self.csn.value(0)
        pyb.udelay(1)
        self.clk.value(0)
        pyb.udelay(1)
        angle_array = [0 for i in range(0,18)]  

        init = pyb.micros()

        for i in range(0,18):
            self.clk.value(1)
            #pyb.udelay(1)
            angle_array[i] = self.do.value()
            self.clk.value(0)
            #pyb.udelay(1)

        end = pyb.micros() - init
        print(end)

        self.csn.value(1)
        self.clk.value(0)

        return angle_array  angle_array 
As you can see, the read() method make the CLK pin to to oscillate.
I'd like to read it more quicly, it would be optimum to reach the 1MHz threshold! Btw, where is the bottleneck? Is writing or reading a Pin a time consuming operation?
I set the frequency of the Pyboard to the higher value, too, but it didn't help much!

Other than that, since for my use-case (designing data acquisition for a Formula-style car) I need a lot of speed (in the sub-millis range), is there something you can suggest me for reaching this goal?

Thank you a lot, I hope to give back something to the community sooner or later! (Hopefully sooner!)

Giacomo

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: Read bit stream from a Serial Interface

Post by deshipu » Wed May 10, 2017 1:56 pm

Use the SPI peripheral.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Read bit stream from a Serial Interface

Post by pythoncoder » Thu May 11, 2017 8:03 am

You may get some improvement if you cache the bound variables in locals:

Code: Select all

    def read(self):
        clk = self.clk
        csn = self.csn
        do = self.do
        csn.value(0)
That may save time with the self lookups (unless Viper has already optimised this away). Other than that I'm not sure there's much more that can be done with the bit banging loop other than using a built-in peripheral interface if this can be persuaded to work.

As a general point I'd allocate the array outside the function as a global or bound variable: this would make read() run a bit quicker and reduce garbage collection.

The more radical options for the loop are writing a C module or using the built in ARM Thumb assembler. I'd go for the latter to avoid modifying the firmware, but that's just a personal preference.
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Read bit stream from a Serial Interface

Post by Roberthh » Thu May 11, 2017 8:24 am

If using the SPI module works, like suggested by @deshipu, that's truly the most elegant way. Using viper modules, you can access the port registers directly. That takes about twice the time than directly using assembler, but still as fast as you can get anyhow with the I/O section of the controller. You'll find code samples for PyBoard in this file:https://github.com/robert-hh/SSD1963-TF ... /TFT_io.py

giacomoalbe
Posts: 9
Joined: Thu Dec 22, 2016 10:15 pm

Re: Read bit stream from a Serial Interface

Post by giacomoalbe » Thu May 11, 2017 8:55 am

Thank you guys for your help, really appreciated!

I don't think that the SPI solution would work, since it seems to me that the two interfaces are different, but I think I'll have a try.

The

Code: Select all

@micropython.asm_thumb
solution seems promising, since that way I'll have a lot more control over the clock duration (for example) and for accessing the GPIO, so I'll definitely give it a try!

As @Roberthh suggested, the TFT controller is very useful since it uses both the

Code: Select all

@micropython.viper
and

Code: Select all

@micropython.asm_thumb
decorators and since I think I'm going to use both (preferably the ARM Thumb, since it guarantees more speed which is actually what I want) it would be a really good source of inspiration!

Another question: do you know if it is possible to access any of the ADC through viper o asm_thumb? Since I have to improve the performance of a code which gets the values from 2 ADC!

Thank you again for your help again! Really, really appreciated!

Post Reply