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

PSoC™ 5, 3 & 1 Forum Discussions

Naz99
Level 3
Level 3
10 likes given 25 sign-ins 5 questions asked

hello, I am using psoc 5lp cy8ckit-059 prototyping kit and I want to build a project that uses ADC delsig that can read the input and send it to uart. I want to print the data without using delay because I want it to print every data in a serial monitor but if I run the code, it will crash my serial monitor (see my project attachment). Is there any methods that can let me get all the data and print it without delay? The attachment is my testing for the project with a certain setting on my adc delsig for the project requirement. 

0 Likes
1 Solution
Len_CONSULTRON
Level 9
Level 9
500 solutions authored 1000 replies posted 750 replies posted

Naz99,

Hi.

Code Issues

First off you have multiple problems with your code in main.c.   At least one of the problems will be the cause of many of your issues with crashing your terminal monitor program.

The first major major problem is that you call 

val = ADC_DelSig_1_CountsTo_mVolts( ADC_DelSig_1_GetResult16()); 

inside main().

    for(;;)
    {   
        val = ADC_DelSig_1_CountsTo_mVolts(  ADC_DelSig_1_GetResult16());
        sprintf(send, "%ld\r\n",val);
        UART_PutString(send);
        //CyDelay(100);
    }

You also have the same code

val = ADC_DelSig_1_CountsTo_mVolts( ADC_DelSig_1_GetResult16()); 

in the eoc_isr().

Besides being redundant, using this line in the for() loop of main() will force a read of the ADC even if the conversion is not completed.  This will try to print WHAT EVER value happens to be in the ADC result register IMMEDIATELY.  This makes the other problem you are having worse.  I'll get back to this later.

Data Rate Issue

The major reason for your terminal monitor program crash without using the CyDelay(100) is that you are trying to push data faster than the terminal program can handle.   This is a problem both with your application and with the PC terminal program itself.   I'm assuming you're using Termite.  I get the same crash.

Your application Data Rate mismatch

Let discuss the issue on your side of the 'fence'.

You are forcing ADC conversions at 2MHz/256 = 8000 samples/sec.

Your UART is set to 57600 baud 8N1 (10 bit protocol).  This means you can send out a maximum of (57600 bits/sec)/10 bits = 5760 Bytes/sec.   Since you are using "%ld\r\n" as the output format you are sending out at most 4 chars for the %d and 2 chars for the \n\r.  This is 6 chars (Bytes) for every sample output.  Hence 6 Bytes/sample.

Since your maximum UART output is 5760 Bytes/sec then your sample output rate supported is ((5760 Bytes/sec)/6 Bytes/sample) = 960 samples/sec.

In summary: Your intended ADC output is 8000 samples/sec.  Your UART sample rate is 960 samples/sec.

Therefore you have a bottleneck issue using the UART at 57600 baud.   You cannot send the data out at the rate read by the ADC.

Now let's get back to the code issue I mentioned:  Since you are not waiting for the conversion to complete, you are reading the data IMMEDIATELY.  Therefore you are reading the ADC FASTER than the 8000 samples/sec you are targeting.  This makes your problem potentially worse.

Here's the good news (finally!):  You are using the UART_PutString() which is a blocking function.  This means you cannot send data any faster than the UART can send (960 samples/sec)  This means even if you want read the ADC every 8000 samples/sec, you don't return back to the 

val = ADC_DelSig_1_CountsTo_mVolts( ADC_DelSig_1_GetResult16()); 

statement until the UART_PutString() function is fully complete.

The Terminal Monitor Program Issue

Virtually every PC terminal program has a problem when you are trying to send continuous serial data at high speed (>= 9600 baud).   Some programs will crash.  Some will hang. 

This is because the program usually tries to dump the characters to the screen.  Most likely the screen drawing graphics program cannot keep up.  If you were dumping the data to an old terminal monitor (non-PC) you will probably be more successful since they only store one screen of data rather than store it for data logging.

Summary

The CyDelay(100) works because you are slowing the data output to about 100 samples/sec to the terminal.

Suggestion #1

Change the ADC sample rate much lower.   I modified your project to sample at 100 samples/sec.   Using Termite, it appears to be stable as long as a deselect "Keep history" in the "Settings". 

Modified Project Attached.

Suggestion #2

If you must keep a higher ADC sample rate, take advantage of 'window' averaging technique.  For example if you ADC sample at 8000/sec and UART output at 100 averaged samples/sec then you can take 8000/100 = 80 ADC samples to provide a single averaged output at 100/sec.

Modified Project Attached.

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

View solution in original post

2 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Hi;
I would suggest you to upgrade Creator to latest version (4.4)
There are two points to observe: you are reading a conversion value from within the interrupt handler AND from your main-loop.
Choose only one and keep in mind that global variables changed by an interrupt handler need to be declared as "volatile".

The UART is comparably slow. The ADC samples with 128 µs and the output of the UART will take a lot more time, in your case about 2ms per character.

Hope that infos will help you to get your project running.

Happy coding
Bob

0 Likes
Len_CONSULTRON
Level 9
Level 9
500 solutions authored 1000 replies posted 750 replies posted

Naz99,

Hi.

Code Issues

First off you have multiple problems with your code in main.c.   At least one of the problems will be the cause of many of your issues with crashing your terminal monitor program.

The first major major problem is that you call 

val = ADC_DelSig_1_CountsTo_mVolts( ADC_DelSig_1_GetResult16()); 

inside main().

    for(;;)
    {   
        val = ADC_DelSig_1_CountsTo_mVolts(  ADC_DelSig_1_GetResult16());
        sprintf(send, "%ld\r\n",val);
        UART_PutString(send);
        //CyDelay(100);
    }

You also have the same code

val = ADC_DelSig_1_CountsTo_mVolts( ADC_DelSig_1_GetResult16()); 

in the eoc_isr().

Besides being redundant, using this line in the for() loop of main() will force a read of the ADC even if the conversion is not completed.  This will try to print WHAT EVER value happens to be in the ADC result register IMMEDIATELY.  This makes the other problem you are having worse.  I'll get back to this later.

Data Rate Issue

The major reason for your terminal monitor program crash without using the CyDelay(100) is that you are trying to push data faster than the terminal program can handle.   This is a problem both with your application and with the PC terminal program itself.   I'm assuming you're using Termite.  I get the same crash.

Your application Data Rate mismatch

Let discuss the issue on your side of the 'fence'.

You are forcing ADC conversions at 2MHz/256 = 8000 samples/sec.

Your UART is set to 57600 baud 8N1 (10 bit protocol).  This means you can send out a maximum of (57600 bits/sec)/10 bits = 5760 Bytes/sec.   Since you are using "%ld\r\n" as the output format you are sending out at most 4 chars for the %d and 2 chars for the \n\r.  This is 6 chars (Bytes) for every sample output.  Hence 6 Bytes/sample.

Since your maximum UART output is 5760 Bytes/sec then your sample output rate supported is ((5760 Bytes/sec)/6 Bytes/sample) = 960 samples/sec.

In summary: Your intended ADC output is 8000 samples/sec.  Your UART sample rate is 960 samples/sec.

Therefore you have a bottleneck issue using the UART at 57600 baud.   You cannot send the data out at the rate read by the ADC.

Now let's get back to the code issue I mentioned:  Since you are not waiting for the conversion to complete, you are reading the data IMMEDIATELY.  Therefore you are reading the ADC FASTER than the 8000 samples/sec you are targeting.  This makes your problem potentially worse.

Here's the good news (finally!):  You are using the UART_PutString() which is a blocking function.  This means you cannot send data any faster than the UART can send (960 samples/sec)  This means even if you want read the ADC every 8000 samples/sec, you don't return back to the 

val = ADC_DelSig_1_CountsTo_mVolts( ADC_DelSig_1_GetResult16()); 

statement until the UART_PutString() function is fully complete.

The Terminal Monitor Program Issue

Virtually every PC terminal program has a problem when you are trying to send continuous serial data at high speed (>= 9600 baud).   Some programs will crash.  Some will hang. 

This is because the program usually tries to dump the characters to the screen.  Most likely the screen drawing graphics program cannot keep up.  If you were dumping the data to an old terminal monitor (non-PC) you will probably be more successful since they only store one screen of data rather than store it for data logging.

Summary

The CyDelay(100) works because you are slowing the data output to about 100 samples/sec to the terminal.

Suggestion #1

Change the ADC sample rate much lower.   I modified your project to sample at 100 samples/sec.   Using Termite, it appears to be stable as long as a deselect "Keep history" in the "Settings". 

Modified Project Attached.

Suggestion #2

If you must keep a higher ADC sample rate, take advantage of 'window' averaging technique.  For example if you ADC sample at 8000/sec and UART output at 100 averaged samples/sec then you can take 8000/100 = 80 ADC samples to provide a single averaged output at 100/sec.

Modified Project Attached.

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