Page 1 of 2

[SOLVED] Polling pin at 13_us rate ?

Posted: Tue Jul 28, 2020 3:24 pm
by pidou46
Hi,

I'm willing to read data from Chinese digital dial gauge.

This have been successfully been done with arduino microcontroller.

Here are some references:
https://www.davidpilling.com/wiki/index.php/DialGauge
http://www.shumatech.com/support/chinese_scales.htm
https://web.archive.org/web/20180730194 ... n-arduino/

On my side I would like to do it with esp32 and micropython.

The communication protocol is based on:
- a clock line : ticking at 77Hz to 90Hz depending on exact device used
- a data line : bits are read synchronically with clock line

Is there a way to poll a pin at this rate (13_us) ?

Either pcnt or rmt devices from esp32 would be a good way to do it but they are not supported yet.

Re: Polling pin at 13_us rate ?

Posted: Tue Jul 28, 2020 11:54 pm
by jimmo
Is it 77 Hz or kHz -- if it's only Hz then its 13ms, which might be fine to just poll.

Sounds like what you want is SPI peripheral mode, but unfortunately I don't think that's supported on ESP32 MicroPython? RMT receive would also be useful.

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 5:28 am
by pythoncoder
The rates on those web references vary. The dial gauge ref shows 5 clocks in a 2ms period i.e. 400μs interval which should be manageable. For the faster devices I'd recommend a Pyboard (V1.1 or any D series).

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 6:47 am
by pidou46
Thanks for your answers,

I've made a typo, the clock is rated at 13_us (77_kHz)

But it's quite different from one device to another.

I've made some test to check if I would be able to manage the dial gauge case (400_us)

Code: Select all

from machine import Pin
import time

pin=Pin(12)

while True:
    pin.value()
    print(time.ticks_us())
result:

Code: Select all

92386809
92387675
92388534
92389400
92390259
92391125
92391984
92392857
92393709
92394575
So about 860_us, quite disappointing...

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 7:15 am
by pidou46
pcnt support would help a lot in this case.

There have been some attempt to implement it, but what I have understand is that it's not wanted to add it to the firmware like it have been done with RMT to avoid bloating it.
https://github.com/micropython/micropython/pull/5496

On an other hand, it have been some effort to find a mechanism to call platform-dependent functions but it stall (the PR is closed)
https://github.com/micropython/micropython/pull/5653

Does I understand it well ? maybe I could rise an issue on github, but I don't want to beat a dead horse.

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 7:20 am
by Roberthh
In your example printing 8 digits + CR + NL at 115200 baud takes about 860 µs (100 bits / 115200 bits/s).

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 9:13 am
by pidou46
good point Robethh !

With a modified version of the test script:

Code: Select all

from machine import Pin
import time

data=[]
pin=Pin(12)

for _ in range(10):
    #time.sleep_us(1500)
    pin.value()
    data.append(time.ticks_us())
    
print(data)
I get:

Code: Select all

[code][395274683, 395274763, 395274800, 395274837, 395274873, 395275040, 395275077, 395275113, 395275150, 395275232]
[/code]

This gives between 36 and 167_us

So as pythoncoder have stated I may be able to manage 400us signal ?

Disabling IRQ would help to get more stable result ?

Now I've to order a dial gauge and try.

Still, PCNT would be a nice addition and would allow to read from several devices...

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 9:29 am
by pidou46
I've tried to disable IRQ:

Code: Select all

from machine import Pin
import machine
import time

data=[]
pin=Pin(12)

state=machine.disable_irq()
for _ in range(10):
    #time.sleep_us(1500)
    pin.value()
    data.append(time.ticks_us())
machine.enable_irq(state)
print(data)
It doesn't really help, I get result from 29 to 158_us

I have tried to disable the garbage collector, but it doesn't help much neither

Is there some tricks to get a better result ?

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 10:19 am
by Roberthh
- data.append() is slow. Better add to a pre-defined array.
- you might try native or viper code.

Re: Polling pin at 13_us rate ?

Posted: Wed Jul 29, 2020 10:43 am
by Roberthh
So I have a version is is slightly faster, at least from the second sample on. Sampling times are 119µs(first pair) and 7 µs (following pairs) on a non-spiram board and 161 / 20µs on a SPIRAM board.

Edit: Code improved to 138/5µs on spiram board and 119/5 on a non-spiram board.

Code: Select all

from machine import Pin
import machine
import time
from array import array

data=array("l", 10*[0])
pin=Pin(12)

@micropython.viper
def sample(data, p, t):
    state=machine.disable_irq()
    for _ in range(10):
        p()
        data[_]=t()
    machine.enable_irq(state)

def run():
    sample(data, pin,  time.ticks_us)
    for _ in range(9):
        print(data[_ + 1] - data[_])