PSoC4 - ADC scan never finishes (or starts?)

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

cross mob
Anonymous
Not applicable

Hi,
First-time PSoC4 user/noob here. I've got a few of the CY8KIT-049-42xx kits (specced by customer - chip is CY8C4245AXI-483) and am trying to work from the CE95272 (Diff. PreAmplifier) application note to put together a simple multichannel ADC-sampling-to-UART-port proof of concept. However, after starting the ADC, the example hangs waiting for the ADC to be 'done' (dataReady asserted) - the interrupt never fires. When I replace this with a polling loop to report the value of ADC_IsEndConversion(ADC_RETURN_STATUS), it just reports 0 (not finished) always.

   

Tried so far:

   
        
  • Ensured correct chip ise selected (Project -> Device Selector)
  •     
  • Update all TopDesign.cysch components (Project -> Update Components - most were version 1.x; ADC now at version 2.30)
  •     
  • Remove the flag-check from the ISR so that any hit to ADC_ISR_Handler will assert dataReady (for testing) - nothing
  •     
  • Confirm configuration of SAR ADC: all defaults from the example except for sample rate     
            
    • Sample rate 150Hz, within range specified to the right of it, which I assume refers to the legal range according to the current clock configuration?
    •       
    • Clock source Internal
    •       
    • Sample mode Free running
    •       
    • Vref: Internal 1.024V, single-ended neg. input Vss
    •       
    • Result format signed, right-justified, 128 averages, alt. resolution 8 bits, averaging mode 'Fixed resolution'
    •       
    • A/B/C/D clocks: 4
    •       
    • Sequenced channels: 4 (0, 1, 2, 3 - 2 diff, 2 SE)
    •       
    • Confirm ADC pin assignments in *.cydwr look OK and are valid for the kit
    •      
  •    
   

    
Note, the "ADC_IRQ_StartEx(ADC_ISR_Handler)" call in the example to register the interrupt handler isn't in the ADC documentation, but "ADC_IRQ_Enable()" (not used in the example) is. Adding this seems to have no effect.

   

For testing, my 'main loop' now consists of:

   

    for(;;)
    {
      while(dataReady == 0u) // <-- hung here
        {
            //; /* Wait for ADC conversion */
            UART_UartPutString("\r\nADC Status: ");
            UART_UartPutChar( (uint8_t)ADC_IsEndConversion(ADC_RETURN_STATUS) + CONVERT_TO_ASCII);

   

        }
        // ...unreached code here...
    }

   

The output is a neverending stream of "ADC Status: 0" messages.

   

Is there any special (chip-specific?) trick I'm missing to getting the ADC to start/finish conversion, or any advice on how to debug this further?

   

Thanks!

0 Likes
14 Replies
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received
        Please post your code so we can check it.   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the forum.

   

As bobgoar said: Can you please post your complete project, so that we all can have a look at all of your settings. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.

   

 

   

Bob

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

Bobs,

   

Here is the workspace archive.

   

Thanks!

0 Likes
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received

I checked the sample program and it is working and changing channels and has AD data.  The only thing I did was update the components to run on Psoc Creator 3.3. I didn't add the resistors in the original design just loaded the project and ran it.  I did change the reference voltage from 1.024 to 1.024 bypassed as it didn't like the clock frequency and it was displaying a Red !.
It said the clock frequency was outside the requirements.

0 Likes
lock attach
Attachments are accessible only for community members.
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received

Drmn: I removed this code  // debug: example code hangs here; try to see if the ADC is actually doing anything
           // UART_UartPutString("\r\nADC Status: ");
           // UART_UartPutChar( (uint8_t)ADC_IsEndConversion(ADC_RETURN_STATUS) + CONVERT_TO_ASCII);

   

And turned this back on

   

 if(SW2_Read() == 0u)
        {
           CyDelay(5u);    /* Basic debounce delay */
           if(SW2_Read() == 0u)
            {
              channelFlag = 1u;
               /* Update the channel number */
              channel++;
               channel %= NO_OF_CHANNELS;
            }
          while(SW2_Read() == 0u)
          {
                ; /* Wait till button released */
            }
       }

   

Now it is working fine.  What are the I2C component and the SPI_1.  They where not enabled in your code so I disabled them.  I also disabled your Bootloadable  component as I am using a PSOC 4 Pioneer board. You can turn it back on . Also in the original code the port 0 channel was set to limit detect.  I turned it off in my example and it worked but if you need it you may want to put a check in the limit detect box. Also I changed the UART output pin to P0_5 from P4_1 as I was not using the CY8CKIT-049-42XX kit.

0 Likes
Anonymous
Not applicable

bobgoar,

   

I'm using PSoC Creator  3.3 CP2 (3.3.0.7343), updated yesterday. The components (assuming this means the ADC and other blocks in TopDesign) "should be" up to date since running "Update Components", although I only physically opened the ADC component to visually compare the version number to what currently shows in Creator's component catalog.

   

I took your suggestion of changing the reference to 'bypassed'. This doesn't seem to have made any difference in my code functionally (still showing "ADC Status: 0" always), although the value range shown in brackets next to sample rate / frequency expanded quite a bit with this change. I don't get any warnings / red (!) marks about clock speeds in the ADC configuration for either setting.

   

The SPI and I2C blocks don't do anything yet. I know I will need those interfaces for other sensors once the simple stuff like ADC is working, but they're not used yet. (The "dedicated hardware peripheral [SCB] and/or just synthesize one up as needed" approach used by PSoC is still kind of black-box voodoo to me; planting the blocks and checking for compiler/fitter errors seemed like the easiest way to confirm the on-chip resources existed to support I2C/SPI master plus the UART uplink back to the PC.) I do get a couple clock warnings in the compiler output relating to these modules, but I doubt they're related to the ADC issue.

   

UPDATE: I accidentally managed to unplug and replug the kit while a terminal emulator program was still connected to its virtual COM port. I lost any ability to connect/program on this port after that, but sitting on the terminal output were four glorious lines of: "Channel 1 = -0043 mV"

   

After a little experimentation, it looks like the ADC is occasionally working for a very short time after startup (shorter than the time it takes to plug it in and then connect to the resulting COM port manually); amazingly, plugcycling the kit WHILE attached to the port not only seems to work, but I get ADC readouts for a couple seconds before the kit goes back to hanged waiting for dataReady / nonzero ADC status. Terminal output after plugcycling:

   

ADC Status:1 = 0091 mV

   

ADC Status: 0
             Channel 1 = 0088 mV

   

ADC Status: 0
             Channel 1 = 0086 mV

   

ADC Status: 0
             Channel 1 = 0083 mV

   

ADC Status: 0
             Channel 1 = 0079 mV

   

ADC Status: 0
             Channel 1 = 0078 mV

   

 

   

ADC Status: 0
             Channel 1 = 0016 mV

   

ADC Status: 0
             Channel 1 = 0012 mV

   

ADC Status: 0
ADC Status: 0
             Channel 1 = 0011 mV

   

ADC Status: 0
             Channel 1 = 0007 mV

   

ADC Status: 0
             Channel 1 = 0006 mV

   

[...]

   

ADC Status: 0
             Channel 1 = -0097 mV

   

ADC Status: 0
             Channel 1 = -0098 mV

   

ADC Status: 0
             Channel 1 = -0101 mV

   

ADC Status: 0
ADC Status: 0
ADC Status: 0
ADC Status: 0
ADC Status: 0
ADC Status: 0
ADC Status: 0

   

It seems like "something" is making the ADC unhappy after a little while. Are there known issues if the ADC completes more than one scan between readouts / polling the status flag, or trying to read/poll it "too fast"?

0 Likes
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received

I was talking about the example project you referenced in the first post.  I had to update that example and fix the frequency and the reference voltage.  I was able to get it to work for 20 minutes before I disconnected it and put the Pioneer kit back in its box.  It maybe a stack issue try increasing it from 100 to 400 and see if that fixes it. Have you tried the program I sent you?

0 Likes
lock attach
Attachments are accessible only for community members.
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received

Here is another program that you may want to review it has a 6 channel volt meter and displays it on a LCD it also writes to a terminal program.  It is made for the CY8CKIT-049-41XX but works great with the CY8CKIT-049-042XX boards. I had this running for months.

0 Likes
Anonymous
Not applicable

Thanks for the suggestions. Stack was already 0x400; I tried bumping heap up as well; no change (it *shouldn't* be using the heap, but...)

   

I haven't tried these different examples yet, but will when I have time. Since this will ultimately be delivered to a customer though, I'd really like to understand the issue that is happening rather than hail-mary my way around it with different canned code-samples until the issue appears to go away (only to potentially come back later).

   

>>> Also in the original code the port 0 channel was set to limit detect.

   

You may be onto something here! I discovered I can get the dead ADC to "reanimate" for brief periods at a time by rubbing my fingers over the respective analog port pins(?!?!?!). (The pins are currently unconnected/floating as this is basically a software smoke-test at this point.) This seems like behavior consistent with a conditional detection feature, but disabling the "Limit detect" for all channels or modifying the thresholds/condition under "Interrupt limits" in the ADC component has no effect. I would be led to assume that the "Interrupt limits" values *should* only apply if the "Limit detect" feature is enabled for at least one channel, and also that the interrupt this feature would generate is independent of (does not gate) basic ADC sampling operation and status reporting, but hopefully someone with experience can say for certain. The documentation seems to suggest this is an independent feature that generates a separate interrupt, allowing the CPU core to stay in sleep (assuming ADC done interrupt is disabled) until the limit condition occurs.

   

I also tried removing the opamp stuff from the appnote example, replacing those inputs with analog pins and setting them all to single-ended. This changes, but does not eliminate, the stuck-ADC behavior (now it tends to return values more often, but can still be stuck/unstuck by running fingers across the analog pins).

   

Any ideas?

0 Likes
rola_264706
Level 8
Level 8
50 likes received 25 likes received 10 likes received

Putting your finger on the pins can cause very high AC signals from the air to be detected and that is why it works.  C's volatile keyword is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time--without any action being taken by the code the compiler finds nearby. I was thinking that you need to make your interrupt variables to Volatile as that sometimes helps in the interrupt routines.  

0 Likes
Anonymous
Not applicable

The 'dataReady' flag is already declared volatile; this is what I'm using to detect any hit to the interrupt (the actual status flags are ignored for now, but good call on making the variable these are stored to volatile too). Likewise the actual status and result regs are accessed through vendor-supplied functions, which "should" handle this detail already (if not, I suspect there would be a lot more questions on this subject!). In particular, the ADC progress is continuously polled via ADC_IsEndConversion(ADC_RETURN_STATUS) while waiting for the interrupt - so far, I have yet to see a nonzero result not accompanied by an interrupt.

   

All compiler optimizations are currently disabled (gcc command line options: -mcpu=cortex-m0 -mthumb -Wno-main -I. -IGenerated_Source\PSoC4 -Wa,-alh=${OutputDir}/${CompileFile}.lst -g -Wall -ffunction-sections -O0 -ffat-lto-objects )

   

Any other ideas on what could be going on?

   

Thanks!

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Consider posting your actual workspace bundle.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Please see post #4 for the workspace zip (DataAcqWorkspace.cywrk_.Archive01.zip). Unless there is some data that it's missing?

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I thought you have made some changes since the last upload.

   

 

   

Bob

0 Likes