Guzunty / Pi

This repository contains resources to support the Guzunty Pi IO expansion board
110 stars 32 forks source link

New core request - PWM input #34

Open johhar opened 9 years ago

johhar commented 9 years ago

Could the Guzunty be used to determine the duty cycle of pwm?

campbellsan commented 9 years ago

Yes. Have a look at the gz_ppm core. It does exactly that.

It is adapted for radio control applications, so the PWM rate is quite low, but the core design and sample clock rate could be tweaked to meet your exact needs.

What we would need is a specification of the PWM rate and the desired accuracy to move it forward.

johhar commented 9 years ago

I had already handled the project I was working on a different way. I have retrofitted my house with photovoltaic, solar thermal and water to air and water to water geothermal with radiant heating so there are lots of pumps... Initially, it was all thermostats and relays. I had not even finished this when the Pi came along and with it tighter control. I find these needs tend to reoccur. So I may revisit this in the future with a specific application. I was kind of thinking of a general purpose device which would do something like be ready to report (high count)/(high count + low count) regardless of the frequency (within a range) and at the moment am more asking if this can be achieved with the Guzunty. In the mean time I will take a look at the ppm. Thanks.

johhar commented 9 years ago

Wow that ppm core does pretty cool stuff. I was thinking of something more modest like a readable register with the last (high count)/(high count + low count) fraction. Or two registers containing previous complete high and low counts and I suppose it would need some means of determining 100 & 0% situations.

johhar commented 9 years ago

Having the pi be able to read two previous full count registers would allow determination of frequency also based on clock frequency sent to core. Being able to read high and low wrap (of current counts) flags could be used to determine 100 or 0%. This way it would have alternate functionality in addition to measuring pwm.

The clock could also be divided and fed to replicated registers and allow different range set of registers if there was room to spare.

campbellsan commented 9 years ago

if there was room to spare.

This the key phrase. The CPLD resources are finite. In an FPGA your suggestions would work great. Indeed, if resolution is not so important, these ideas will work in the CPLD too.

A CPLD target often requires a little ingenuity to squeeze the most out of it. One heuristic I use is 'let the host processor do the work where possible'. Here's what I'd do:

Have just one register per channel, reset on the rising edge of the signal. If the register saturates, report all 1's or all zeroes based on the input signal (for 0 & 100% duty). Allow the host to adjust the clock rate so that the register just doesn't roll over at 99.9% duty. Leave the host to do the scaling to a smooth 0 - 100% range.

I agree it won't work for all PWM sources, I think your suggestion of a hi and lo register is the only way to go if the pulse frequency is variable. However, for those signals with a stable pulse rate, I think the proposal above will provide the most channels at the best resolution.

The conclusion is that both core designs are needed depending on source characteristics.

Care to turn your design into reality?

;-)

On 10 Feb 2015, at 03:26, johhar notifications@github.com wrote:

Having the pi be able to read two previous full count registers would allow determination of frequency also based on clock frequency sent to core. Being able to read high and low wrap (of current counts) flags could be used to determine 100 or 0%. This way it would have alternate functionality in addition to measuring pwm.

The clock could also be divided and fed to replicated registers and allow different range set of registers if there was room to spare.

— Reply to this email directly or view it on GitHub.

johhar commented 9 years ago

I see your point. Most of the applications I would use would probably be a fixed (but initially unknown) frequency. My original application would have been to listen in on a ecm pump's signal (hopefully without destroying my pump). I think for many of my projects, ~12 bits of resolution would be plenty. 16 seems like a nice number that might make it have more appeal. So you would have two modes the first would count a rising edge to the next rising edge which would be utilized to determine an optimum clock setting. Once that is set, when a signal is sent the counter is set to 0 where it waits till the next rising edge then counts to the falling edge and then does not change. Would you generate an interrupt, change a pin state or just depend upon successive reads to determine completion?

Care to turn your design into reality?

Well as I said, I moved on from my original goal. My plumbing became more complex with differing flow paths possible. So knowing the pump speed did not really give an accurate picture of flow. However my next idea might be made to work within the same or a very similar core. About 6 months ago, I was playing with an ultrasonic range finder and found that the accuracy was not so hot reading the return pulse time with the pi. I tried with both polling and generating an interrupt. It had occurred to me I might use two range finders which only cost a few bucks at either end of the pipe (maybe the second would have the speaker disabled) as an ultrasonic flow meter. This would require a fairly accurate counter and temperature compensation (which I am already monitoring) and echoing the trigger pulse on one of the pins (for the range finder). Also the consistency of the range finder would have to be pretty good and the frequency such that it propagates well in liquid, but some things you find out by trying. So maybe I am suggesting a 3rd version which would be an arbitrary interval counter or timer with much better resolution than the pi. Obviously you want these things to be useful for as many applications as possible, but the rangefinders seem to be popular so a timer ideal for this purpose would probably be a hit. I'll have to look at the velocity of sound in liquids... - but just guessing, I think you would need 16 or more bits to get a meaningful result because the delta-T would be small relative to the no flow travel time, so the flow's resolution would always be much less than the counter resolution. If there were room for multiple channels, you might want the ability to trigger them as a group, pairs (I'm thinking the two rangefinders pointed at each other and reading them both) in addition to independently.

campbellsan commented 9 years ago

Interesting. I have used ultrasound rangefinders in the past, but the ones I have used (HC-SR04 clones) do the timing on board the module. Can you point me at the hardware you are talking about?

johhar commented 9 years ago

You send a pulse on one pin, a pulse is returned on another pin. It's width is proportional to the distance. http://m5.img.dxcdn.com/CDDriver/CD/sku.133696.pdf I was measuring it c code using the wiringpi library. I did enough experimentation to feel that the Pi was the biggest source of inaccuracy. With other threads and interrupts, this makes sense. So with an accurate counter and this (or a better) rangefinder (or a pair pointed at and responding to the other's triggering sonic impulse) could measure flow in airducts and be a nice home automation tool. Having a pair of channels would allow measurement in irregular ducts like the insulated flexible type. If the delta times for velocity measurements were expressed by just a few significant digits, you would obtain higher effective resolution by averaging many reads.

campbellsan commented 9 years ago

Yeah, that's the same design I have used. I used an Arduino with an interrupt on the echo pin, it seemed to work just fine. Yes, the interrupt latency of Userland ISR's in Raspbian has been measured at between 25 and 75 us, which I suppose does impose significant noise on the sensor output. The CPLD could definitely give a more accurate result, but you'd need quite a long counter register to handle the sensors output range, probably 15 bit counters, one for each sensor.

That's pretty easy to do and you could get an interrupt on each reading.

johhar commented 9 years ago

Could you have a series of clock^.5 and programmatically select which tap would feed your counter? Then you could maintain high resolution for the timer range without manipulating the system clock. For that particular device it would be easy to start at some power of two tap that would measure the the maximum possible pulse length then repeat the reads moving up one tap until the count > MAXCOUNT/2

Another possibility calculate time with the system clock based on start and stop timestamping interrupts A fast clock counter had a sufficient bitlength to cover PI latency could be zeroed on start, allowed to wrap until stop. Use the system timestamps to calculate the number of wraps then correct it with your register. This way you could time arbitrary intervals with maximum precision.

johhar commented 9 years ago

Continuing from the last paragraph, the wrapping version's registers would have to be able to hold double the number of clocks of the maximum_interrupt_latency. That and the remainder from the wrap calculation would be used to make the correction. Is there a readable register on the broadcom that gets incremented on the gp_clk? If not, it makes my wrapping strategy a bit less reliable or at least more cumbersome. I was looking at the documentation and didn't see one for this, but it is big and I could have overlooked something. I read a bit about the MASH and see that that might put an upper limit on resolution.

Have multi channels where only one input pin is listened to at a time. When a read is requested for a particular pin, register1 and register2 are zeroed, counting begins on both registers at the rising edge. Register2 freezes on falling edge.

There would also be a 2 bit register to indicate if counting is active for either of the registers - I suppose this could serve as the latch to ready for a read cycle too. This would be readable in the event that the 2nd or 3rd interrupt was generated before the first was done or the reading program timed out.

I don't know what is possible so I'm throwing all of the ideas out to see if you think they are achievable. If so, this core might be able to do a lot of different things and maybe the input pin state could also be read and they could also double as input pins if you are not reading pulse widths.

campbellsan commented 9 years ago

Is there a readable register on the broadcom that gets incremented on the gp_clk?

There is a system timer (p172) and another timer (p196), but I don't know if either or both of these are used by the kernel.

Your ideas are good. Until I built a core, though, I wouldn't know how much of this I could squeeze in, probably not all of it. And here's the beauty of the CPLD, you get to tweak the core to exactly meet the needs of your specific application.

The alternative is to incorporate an Arduino or other microcontroller and using the Pi as a higher level controller that takes care of all the connectivity, you probably know that you can get an Arduino Pro clone from China for a couple of bucks shipped to your door. The ATMega on those boards has timers that are designed to accurately measure time and can be started and stopped on hardware signals.

I'll make a simple, general purpose pulse width input design to start from, but I strongly encourage you to learn VHDL and try these ideas out for yourself. You won't regret it and you're obviously already thinking in the right way.

campbellsan commented 9 years ago

The limiting factor is the number of latches in the design. An XC9572XT has 72 macrocells, with one latch per cell. Each bit in a register uses one latch. Every design needs latches for general logic, and you need a few bits to implement (say) an SPI interface to get the data out to the host so you've probably got about 64 bits to play with in practice. You can tweak the design to have more registers with fewer bits or vice versa.

One thing that occurs to me as I read your ideas is an alternative to lots of registers clocked at different rates. Instead, you have one large register and you read out different parts (vhdl slices) of it to get your fast and slow counts. Look at the servo driver core (4s8o8i) for an example of that; the lower 9 bits of a larger counter are used to time the pulse width, while the upper bits control the frequency of the pulse itself.

johhar commented 9 years ago

I thought of what may be a simplification. Skip zeroing the registers. A cycle could be thus:

write 00 to the two bit register. Lets call it CR for ControlRegister. Write a mask to PortSelectionMask for example 0010 would select #3 of 4 ports bitwise anded to input pins. (this step could be outside the cycle if you only monitor 1 pin) Read both count registers 1 & 2. Increment CR. It's states as follows: 01 Do nothing until rising edge. 10 Clock increments Register1 only. Till Falling edge. 11 Clock increments Register2 only. Till Rising edge. 00 Done. Do nothing.

CR would be incremented and an interrupt generated at the 3 edges.

I think this would achieve all of the objectives mentioned in this thread and be used in several different ways. Timer, PWM input, frequency counter... You could also do some weird ones by writing multiple high bits to PSM.

alternative to lots of registers clocked at different rates. Yea, no point in that. I got your notion, keep the core simple as possible, have the back end on the Pi figure things out like how many times the registers wrap and which way to correct total time and ultimately what the function is. Even using the system clock and a different gpclk shouldn't be to much of a problem.

learn VHDL You are probably right - but my wife says I need to get the radiant floor going in the house and its freezing here. One problem with being a tinkerer is that while one project lurches along, the others stay still.

johhar commented 9 years ago

Somebody might like CR to be echoed on pins.

johhar commented 9 years ago

Presuming the above could fit in a core, a bit might be anded to the MSB of the CR to allow it to run in a continuous or multiple read mode.