PSoC5LP Digital Multiplexer control without using digital pins?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
IsBe_4812011
Level 1
Level 1
5 likes given First like given Welcome!

I am trying to use the PSoC5LP to measure 12 flowmeter signals, which are essentially pulse frequency modulated signals. To do this, I initially tried to use a UDB counter for each signal using the setup shown in CE95350 [EDITED: https://www.cypress.com/file/144696/download ]. However, I found that I was unable to pack the digital design into the 24 UDBs (12 counters + 1 shared PWM), so instead I am splitting the signals into 3 groups and using digital multiplexers to sample them. My question is: how can I control the multiplexer without exposing pins? My current hack is to define a width=2 set of pins and then controlling them using Pin_Write(). I think this comes down to not understanding how to use bus signals from other PSoC components, but I just want to set it up so the multiplexers cycle through the signals at some frequency.

Thanks

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

IsBe,

Here's another project with a 12 input frequency counter that doesn't use a mux. It uses about 62% of the UDBs for the PSoC5.

The clock frequency measurement is from 4 Hz to 996 Hz.  The frequency resolution is +/- 2Hz.

This project is only HW in the TopDesign.  The SW has not been created.

You need to create 12 ISRs.  One ISR for each rising edge of the sync'd input.  In the ISR you need to read the Status Register for that input and substract it from the previously read value.  The count diff(erence) is compared to a frequency chart I list in the page "Counter_Diff_Chart".

Since the 7-bit (plus Toggle FF) is continuously running, if the subtraction comes up negative you need to account for the 8-bit counter wrap-around effect.

Len

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

23 Replies
lock attach
Attachments are accessible only for community members.
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

IsBe,

I've attached a project based on CE95350 that has 12 Pulse Counting Circuit and one 16-bit PWM with NO muxs.  It fits in a PSoC5LP used on the Cy8CKIT-059..

Is this what you are looking for?

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hi LePo,

Sorry, I realize I copied the wrong code example code. I want to implement a 12-channel version of this frequency counter example: https://www.cypress.com/file/144696/download

Thank you for the response!

0 Likes

IsBe,

OK.  Different project.

Before I try to explore options for you can you supply the following information?

  • Maximum Frequency to be counted.
  • minimum resolution of the resolved frequency measured.

The example you linked uses a 32bit Counter.   This is one of the reasons a 12 input frequency counter is going to consume ALL the UDBs and then some.

If you don't need a high resolution to can get the Counter Reference Frequency (the >clk input) closer to input frequency to be measured.  Therefore you can use a 16bit counter or even better a 8bit.

The example you cited claims to be able to measure from 20Hz to 8MHz.  The measurement window is 50ms.  With a 32bit Counter at 24MHz clocking, A 8MHz input will count 1-3 pulses.   This is fairly low resolution.  The result is either considered as 12MHz, 8MHz or 4MHz.  A resolution of +/- 50%

A 32bit Counter at 24MHz clocking, A 20Hz input will count be 599,999 to 600,001 pulses.   This is extremely high resolution of 3ppm (0.003%)

If you don't need that wide of a range, you can make good compromises that might allow you to measure 12 inputs without a mux.

A decent rule of thumb is to use a Reference clock that is 20 times the input to sample.  The resolution would be +/- 10%.   If you need more, make the clock 20 times higher.  Resolution = +/- 1%.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
IsBe_4812011
Level 1
Level 1
5 likes given First like given Welcome!

Hi LePo,

Yes, sorry about that. And absolutely: These signals are relatively low frequency, and the nominal max frequency on the transducer datasheet is 235Hz. In my own project, I reduced the resolution of each counter to only 8 bits (because of what you mentioned, the 32 bit counter is overkill), and captured them with a period of ~100ms. However, this setup still gave me that UDB consumption error.

Thanks again for your help

0 Likes

IsBe,

Nominal is 235Hz.   What is the minimum and maximum value yo need to measure?  What is the frequency resolution you need?  +/- 1Hz?

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
lock attach
Attachments are accessible only for community members.

IsBe,

Here's another project with a 12 input frequency counter that doesn't use a mux. It uses about 62% of the UDBs for the PSoC5.

The clock frequency measurement is from 4 Hz to 996 Hz.  The frequency resolution is +/- 2Hz.

This project is only HW in the TopDesign.  The SW has not been created.

You need to create 12 ISRs.  One ISR for each rising edge of the sync'd input.  In the ISR you need to read the Status Register for that input and substract it from the previously read value.  The count diff(erence) is compared to a frequency chart I list in the page "Counter_Diff_Chart".

Since the 7-bit (plus Toggle FF) is continuously running, if the subtraction comes up negative you need to account for the 8-bit counter wrap-around effect.

Len

Len
"Engineering is an Art. The Art of Compromise."

Hi LePo, this looks great, thanks for all your help!

0 Likes
lock attach
Attachments are accessible only for community members.

IsBe,

The easiest way to measure frequency from 12 flow meter tachometers is to use the FanController component (demo project is attached).

The FanController component can read up to 16 tachometers, limited to input frequency from 16 to 2048 Hz (dynamic range 1:128), providing resolution about 0.1Hz. It is possible to change input range to, e.g. to 8-1024Hz by changing the CLK_TACH_500kHz inside the component from 500kHz to 250kHz. There are few drawbacks of this approach, like wasting of several UDB blocks, as control outputs are not used, and low dynamic range (1:128). The good thing is that no coding is necessary, and existing dynamic range exceeds requirements of a low-cost flow meters, which have typical dynamic range of 1:30.

/odissey1

Figure 1. Test clock (200Hz) and FanController as a tachometer.

FanController_01a_basic_A.png

Figure 2. FanController output of 16 channels measurement, 0.5 sec/block

FanController_01a_basic_UART.png

0 Likes
IsBe_4812011
Level 1
Level 1
5 likes given First like given Welcome!

+/- 1Hz is fine, yes!

0 Likes

Just to give some food for thought.

Another way to solve this problem is to have two UDBs datapath:

1) Counter datapath.

- It can be 16 or 32 bits.

- It has a capture input. It captures on any rising edge of any of the inputs.

- It runs continuously.

2) Mask datapath

- Each input has one bit

- Datapath is configured as PI (Parallel input)

- It has a capture input. It captures on any rising edge of any of the inputs.

- Each input bit is linked to a rising edge detection for the given input.

In the firmware side, it triggers an interrupt on capture. It reads the Mask FIFO to find out which inputs has a rising edge. It reads the counter FIFO and update an array containing the latest count values for each of the inputs masked. You can measure the period of two consecutive rising edges of every input.

0 Likes
lock attach
Attachments are accessible only for community members.

Rodolfo,

Thank you for your suggestions.

Your recommendations do increase the frequency resolution by using 16, 24 or 32 bits for the counter.  However they potentially both have issues when considering that any of the 12 inputs can occur at any time and can occur virtually at the SAME time.

I've attached a new project based on much of your ideas.  It uses a 32bit Timer with capture input.  This should increase the frequency resolution and minimize count wrap-around compensation (It still needs to be compensated).  I also configured for 16 inputs.  I also set the clock to the USB IMO setting 24MHz +/- 0.25% for increased measurement accuracy

The TopDesign has two sheets (only one is needed).

One is "Combined_ISRs" that use only two ISRs.  It requires the app developer to determine which of the 12 inputs have caused the rising edge to generate the ISR.  One ISR is attached to one GPIO port and the other to another GPIO port.

The other sheet is "Individual_ISRs" that use an ISR for each input.  Since each ISR is individualized, it makes it simpler and smaller code.

In either of the sheets, the capture input is used to 'increase' the frequency accuracy.  However it is not clear in the datasheet if the Capture FIFO reads the same Capture value if more than one capture occurs and the FIFO is 'empty'.

If the FIFO provides an invalid value on multiple _ReadCapture() calls, then the app developer needs to abandon the capture FIFO and read the Counter value directly via _ReadCounter().  This method suffers from a little less accuracy since the counter value is constantly updated and depends on how fast the CPU can process the ISR.

Len

Len
"Engineering is an Art. The Art of Compromise."

Hi Len,

The idea is to have a single interrupt. There is no need to have individual ISRs, because as you stated, if all rising edges occur at the same time, you would get an accuracy issue.

If we have a single interrupt, it is actually a good thing to have all rising edges at the same time on the method I have in mind. You would only have one element in the FIFO to sort it out.

The method I proposed would have an issue if all the inputs have a slightly different rising edge, enough of one cycle of the counter clock. In this scenario, you would see an overflow in the buffer. This wouldn't affect the accuracy, but you might miss some measurements.

To solve this, you could use a DMA to quickly save the FIFO values to the SRAM in a circular buffer, and then later on have the CPU to sort it out.

Going back to your project, you can substitute the array of ISRs with a 16-bit datapath configured with PI (parallel input). A0 should be loaded to FIFO on the same capture signal as the one connected to the Timer_Count.

You can add an single interrupt on the Timer_Count interrupt terminal. Or you can have your 16-bit datapath to generate an interrupt on level.

I'm not sure if you can use the "irq" signal from the pins. You need to clear that interrupt in firmware. Ideally you want to use the rising edge detection handle totally in hardware. You can use a DFF + NAND for each of the inputs.

0 Likes
lock attach
Attachments are accessible only for community members.

Rodolpho,

I've created two working projects.  One with a version of your concepts (Port isr with a  16bit Timer capture) and the other with my concept (individual ISRs and 16bit SRs).

I found that your concept definitely uses much less PSoC resources even when allocating 16 pins for inputs.  However BUS_CLK running at 24MHz and having 8 input stimuli the frequency counts measured vary significantly.  I believe this is because the CPU processing is creating delays in reading all the pins on the port if the Port isr is triggered.  This delay is reading the 'live' count of the timer when the Timer FIFO is empty.  I'm also creating conditions with simultaneous rising edges as a "worst-case".

It is even more degraded when one of the inputs is at 100KHz (ILO).  Update:  Using the PLL set to 76MHz and the BUS_CLK=PLL helps to improve the results.

My concept which uses a pair of Status Registers for each pin input can only allocate 12 pins (24 SRs).  At  BUS_CLK=24MHz, the frequency count is much more stable.  This is because the SRs are preserved on the input (rising edge) change and each input uses a separate SR pair.

I've attached the two projects for your review.    Each project dumps to a terminal program @ 115.2K 8N1. Both were written for the CY8CKIT-059.

Note:  Your concept [Freq_Measure_16in_ISRs.cyprj] uses the UART through the KitProg.

My concept [Freq_Measure_12inputs_SRs.cyprj] uses my Term component in USBUART mode.  Terminal Support Component Library

This is because all 12 inputs need 24 SRs.  The UART needs at least 3 SRs.  Therefore using the USBUART does not require any SRs.

Len

Update:  I updated the Freq_Measure_12inputs_SRs.cyprj.   Tis project is current set with the schematic page "internal_inputs".   It allows the stimuli to be directly routed to the inputs.  It's a simpler means of unit testing.   If you disable the "internal_inputs" sheet and then enable the "external_inputs" page.   It will disconnect the direct stimuli and you must externally route the stimuli to the input pins.   One more note:  I had to change the pins from "Hi-Z digital" to "Resistive pull-down".  In "HiZ" unconnected inputs could see transitions from neighboring pins being stimulated.

Len
"Engineering is an Art. The Art of Compromise."

Hi LePo, your updated project has been really helpful. I had a question about reducing the amount of SRs in the project. I was wondering if instead of using two SRs for each input, we use a single DMA on each channel in the following way:

For each input: (-> means hardware connection)

pin input -> DMA drq pin; DMA writes timer count to a memory location on input rising edge; DMA nrq pin -> ISR that does the difference calculation

I'm still quite new to this, so apologies if the reason for not doing it in this manner is trivial.

Thanks again for all your help!

0 Likes

IsBe,

... I was wondering if instead of using two SRs for each input, we use a single DMA on each channel ...

Yes.

The DMA method for each channel will improve your count accuracy.  This is because the DMA channel method can read the BasicCounter value through a single "transparent" (this mode is important) Status Register set within a few BUS_CLK counts when the input transitions occur.   This method will significantly lower your PSoC resources used.

Note: Increasing the BasicCounter and Status Register set to 24- or 32-bit will not increase the count resolution.  To increase the count resolution, you need to increase the Clk_Cnt input frequency into the BasicCounter as well as increase the Status Register to read more than 16 bits.

Len

Len
"Engineering is an Art. The Art of Compromise."

Right, increasing the bits simply makes the rollover calculation less frequent.

Thanks Len!

0 Likes

IsBe,

Right, increasing the bits simply makes the rollover calculation less frequent.

This is true.   However, the correction calculation for the counter value wrap-around still needs to be placed in code.   Without increasing the Clk_Cnt input frequency to the counter, adding additional depth of bits only allows for measuring lower frequencies.

For example in the projects I provided, the Clk_Cnt = 2MHz.  Using 16-bits, the lowest frequency that can be measured is Fmin = Clk_Cnt/(2^16) = 2MHz/65536 = 30.5 Hz.  By going with a 17-bit counter the new Fmin = 15.3 Hz, 18-bits => Fmin = 7.1 Hz ...  Therefore a 24-bit counter would allow you to measure 199mHz and a 32-bit measure 465uHz!  

Len

Len
"Engineering is an Art. The Art of Compromise."

Hi Len, I'm trying to integrate the DMAs into your 12 ISR project and am having some issues. Could you update the example with DMAs?

-I

0 Likes
lock attach
Attachments are accessible only for community members.

IsBe,

As you requested.  I have a project the measures frequency on 16 inputs using DMA.

Len

Len
"Engineering is an Art. The Art of Compromise."

Hi Len,

Looks great, thanks!

0 Likes
lock attach
Attachments are accessible only for community members.

Hi Len,

Still not quite what I had in mind. Attached you find what I was originally thinking. Some findings:

- I noticed the UDB Counter doesn't do exactly what I want, so I created my own 32-bit UDB counter. I need to have an option to capture on LEVEL, not on rising edge. The riding edge detection is done in hardware with a DFF.

- It is important to capture the state of the pins with a FIFO, not with a read directly from the pin registers (as you implemented). This can be done with datapath configured as PI. I created a component to implement just that.

- I quickly test this and it seems working. But I didn't add mechanism to avoid overflow on the FIFO.

IsBe_4812011
Level 1
Level 1
5 likes given First like given Welcome!

Len,

In your example, I find that the DMAs are not properly triggering on the drq rising edge after the first pulse. I'm not sure if the drq signal is insufficient to trigger the DMAs OR if the nrq signal from the DMA is not being reset. Any idea how I can solve this?

0 Likes
IsBe_4812011
Level 1
Level 1
5 likes given First like given Welcome!

The above error was solved by connecting one of my sensors to the inputs and trying it without the stim. I believe the PSoC was not able to sufficiently source all 16 inputs when drawing from the debugger, so the voltage drooped. Regardless, it seems to work nicely with my sensors and an external PSU!

Cheers,

-I

0 Likes