1-wire library and pyb.freq()

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.
JimTal001
Posts: 176
Joined: Thu Jul 30, 2015 4:59 pm

1-wire library and pyb.freq()

Post by JimTal001 » Fri Sep 04, 2015 6:12 pm

I've been experimenting with reducing the CPU frequency while logging data to SD and running on battery power.

I am using the 1-wire library to communicate to my thermocouplers. What I have noticed is that the 1-wire library fails to read if the pyboard CPU is somewhere below 120 MHz. Would anyone know why this is the case?

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: 1-wire library and pyb.freq()

Post by blmorris » Fri Sep 04, 2015 6:33 pm

Answering from my phone, so this is all from memory and may be very wrong ;)
As I understand it, the one-wire protocol requires the signal to be sent with a bit-rate that falls within a specified frequency range. I think that the uPy implementation of one-wire does bit-banging in Python, there may be an implicit assumption about the processor frequency to determine the timing; at 120MHz it may fall out of spec.

-Bryan

JimTal001
Posts: 176
Joined: Thu Jul 30, 2015 4:59 pm

Re: 1-wire library and pyb.freq()

Post by JimTal001 » Fri Sep 04, 2015 7:23 pm

Thank you for the response. I did notice a few micro sec delays in the 1-wire code and wondered if they could be somehow be related. Do you believe that there is a frequency lower than 120 MHz that would still work with the 1-wire, pyboard and SD Card? If so, how would I determine these acceptable frequency?

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: 1-wire library and pyb.freq()

Post by blmorris » Fri Sep 04, 2015 7:35 pm

If I'm correct about why one-wire isn't working, then it would require adjusting the parameters in one-wire.py to work with your desired frequency. I think I recall someone reporting that the pyboard and SD card work down at least as low as 30MHz, but that USB stops working at a much higher frequency. I imagine that one-wire should work at a pretty low frequency if the proper adjustments are made, but I can't be much help figuring that part out.

JimTal001
Posts: 176
Joined: Thu Jul 30, 2015 4:59 pm

Re: 1-wire library and pyb.freq()

Post by JimTal001 » Thu Sep 10, 2015 7:11 pm

Currently the 1-wire library works with CPU speed down to 120 MHz. I to need reduce the CPU speed further to reduce power consumptionion. Is there anyone who can identify the issue 1-wire library?
blmorris wrote:

If I'm correct about why one-wire isn't working, then it would require adjusting the parameters in one-wire.py to work with your desired frequency. ... I imagine that one-wire should work at a pretty low frequency if the proper adjustments are made, but I can't be much help figuring that part out.

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: 1-wire library and pyb.freq()

Post by blmorris » Thu Sep 10, 2015 8:38 pm

I don't think that I've found a clear solution yet, but I have dug up a few more clues that might help:

First, there is this detail on timing in the wikipedia entry on 1-Wire:
To send a "1", the bus master software sends a very brief (1–15 µs) low pulse. To send a "0", the software sends a 60 µs low pulse. The falling (negative) edge of the pulse is used to start a monostable multivibrator in the slave device. The multivibrator in the slave clocks to read the data line about 30 µs after the falling edge. The slave's multivibrator unavoidably has analog tolerances that affect its timing accuracy, which is why the output pulses have to be 60 µs long, and the starting pulse can't be longer than 15 µs.
The 1-wire driver for uPy uses 'pyb.udelay()' to achieve microsecond-precision timing for bit-banging the one-wire pin. 'udelay' is defined in 'stmhal/systick.c', which has the following comment starting on line 85, right before the definition of 'sys_tick_get_microseconds':

Code: Select all

// The SysTick timer counts down at 168 MHz, so we can use that knowledge
// to grab a microsecond counter.
//
// We assume that HAL_GetTickis returns milliseconds.
uint32_t sys_tick_get_microseconds(void) {
I haven't yet dug into the code to figure out if changing the clock frequency really does impact the accuracy of 'udelay'; if it does then it seems this is a bug worth fixing.
Need to leave this for now, but I'll dig into it again when I get a chance.

-Bryan

JimTal001
Posts: 176
Joined: Thu Jul 30, 2015 4:59 pm

Re: 1-wire library and pyb.freq()

Post by JimTal001 » Fri Sep 11, 2015 1:26 pm

Thanks for digging in Bryan, looks like the issue is more serious than I thought.

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: 1-wire library and pyb.freq()

Post by blmorris » Fri Sep 11, 2015 1:54 pm

I'm going to retreat a bit and say that I really don't know what is going on here. I did a little testing, and it appears that 'pyb.udelay()' does properly account for changes in clock frequency, at least for periods long enough for me to measure manually. I also checked out the history of 'stmhal/systick.c' and it appears that udelay() has most likely worked correctly since it was introduced over a year ago.

I also don't have any one-wire devices to play around with; at this point I would be examining the traces with a logic analyzer to figure out where it was failing.

Sorry that I don't have a solution yet. I still suspect some sort of timing issue, but more subtle than 'udelay()' simply getting slowed down. I just added a DS18B20+ to my running Digi-Key order, so maybe in a week or so I'll be able to take another look. It is still possible that there is something fairly simple that we are missing, but I have no experience with one-wire so it isn't obvious to me yet.

-Bryan

JimTal001
Posts: 176
Joined: Thu Jul 30, 2015 4:59 pm

Re: 1-wire library and pyb.freq()

Post by JimTal001 » Fri Sep 11, 2015 7:32 pm

I am using the MAX31850 1-wire breakout board (as you may recall). I hope the problem is not unique to this board.

https://www.adafruit.com/products/1727

manitou
Posts: 68
Joined: Wed Feb 25, 2015 12:15 am

Re: 1-wire library and pyb.freq()

Post by manitou » Wed Sep 23, 2015 8:07 pm

I need to do some tests with the analyzer, but looking at the one-wire spec and then at onewire.py, it appears that in addition to pyb.udelay(), the driver is trying to take into account the delay of each micropython statement (say about 5us) in order to arrive at the cumulative delay expected by the protocol. As you slow the system clock, those "statement" timing assumptions will fail, even though udelay() adjusts to the clock frequency ....

There's not much you can do to make onewire.py any faster, so if you need a slower clock frequency, you may need to implement one-wire in firmware/C.
Last edited by manitou on Fri Sep 25, 2015 4:17 pm, edited 1 time in total.

Post Reply