- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need to take an ADC reading at a specific point in received data stream from a wireless system.
First I dropped an SAR_ADC on the project and tested it worked using this code.
ADC_Start();
ADC_StartConvert();
result = ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);
RSSI_Val = ADC_GetResult16();
Next, I set a flag at the point in data reception I wanted to start sample and when I read the flag in main code I do an ADC sample. Trouble is that I do not have control over the point a packet arrives and therfore the sampling of the ADC is not always occurring when I need it.
Would someone have an example how I could start and ADC conversion within the Uart Interrupt routine so that when I get back in main loop the conversion would have been doen at the right time and I can read the value at that point?
Thanks
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One way of doing it is run SAR continuously, oversampled, and
DMA the result to a memory location. Then use packet received flag
to simply 'pick" up the result in the memory location.
Or in packet received start adc, wait for its conversion complete. Would the
SAR be fast enough to meet your needs ?
How much latency can you tolerate from packet received to ADC result ?
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Orbitcom,
The problem might not be in fast handling of the UART message, but because UART is non-deterministic itself. UART has latency, which can be ~0.1sec. For example you are sending in equal intervals "ADC_start",..."ADC_start",..."ADC_start",... but those packets will not arrive at same intervals, there will be some jitter from packet to packet. Even if ADC sampling starts immediately upon packet received, there will be some time jitter relative to the original 'sent' packet.
You need some hard reference to sync ADC sampling. Look at GPS: it has precise global clock TTL each second alongside to slow UART NEMA output.
odissey1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dana,
The idea of running the ADC continuously and storing to memory location via DMA sounds like a reasonable approach.
I have not used DMA before, is it easy to set up? Also, could I simply copy the register the values are being stored into my variable at the point required inside the Uart interrupt?
If si, I could actually save an array of values (one at each received byte) and obtain and average for the entire message.
The incoming data rate is 38k Baud. The packets are small (14 bytes fixed length). They arrive at pseudo random intervals with 3-5 packets per second.
thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have not used DMA before, is it easy to set up?
Yes, there is a wizard in Creator for setup and some good ap notes (Creator also has a number of example projects) -
http://www.cypress.com/?rID=37793 AN52705 Getting Started with DMA
http://www.cypress.com/?rID=82680 AN84810 PSoC® 3 and PSoC 5LP Advanced DMA Topics
http://www.cypress.com/?rID=44335 AN61102 PSoC® 3 and PSoC 5LP - ADC Data Buffering Using DMA
http://video.cypress.com/video-library/search/dma/ Videos on DMA
https://www.youtube.com/results?search_query=dma+psoc Videos on DMA (some overlap)
Also, could I simply copy the register the values are being stored into my variable at the point required inside the Uart interrupt?
Yes. You can even have the DMA run a loop where you auto inc the address where bytes are
going. You supply a pointer to DMA config for this purpose and an inc value in # bytes depending
on what you are transferring. At end of DMA trigger an interrupt and do the average.
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I set up the DMA using the Wizard but do not appear to be getting ADC results int my memory location.
The code generated by the wizard is shown below...
The ADC -> EOC is connected to DMA -> DRQ, the hardware request is "derived" (I also tried rising edge).
RSSI_Val does not appear to be updated with ADC value.
DMA_Chan = DMA_DmaInitialize(DMA_BYTES_PER_BURST, DMA_REQUEST_PER_BURST, HI16(DMA_SRC_BASE), HI16(DMA_DST_BASE));
DMA_TD[0] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_TD[0], 2, DMA_TD[0], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetAddress(DMA_TD[0], LO16((uint32)ADC_SAR_WRK0_PTR), LO16((uint32)RSSI_Val));
CyDmaChSetInitialTd(DMA_Chan, DMA_TD[0]);
CyDmaChEnable(DMA_Chan, 1);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Still cannot get my DMA running for some reason.
By the way, what controls conflict when I attempt to read the memory location the DMA is putting data?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Still cannot get my DMA running for some reason.
By the way, what controls conflict when I attempt to read the memory location the DMA is putting data?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Who told you to use "AUTO_EXEC_NEXT"?
This will not wait for ADC data ready.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It was the wonderful wizard of oz. (DMA Wizard configuration starting from page 21 of Doc no. 001-52705 rev 1. Self described as easy to set up the firmware configuration (ideal for a DMA newbie).
I followed the documented example but set Auto Next to true and Next TD = 0 (to go back and rerun).
What did I miss here?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a SAR ADC connected to my Analog input pin. The mode is set to free running.
The EOC is connected to the "drq" pin of the DMA. The DMA hardware request set to Derived. Then used the wizard again and set number of TD = 1 and select "Loop".
I start the ADC in code and also have used code below. The RSSI_Val remains at "0". If I remove the DMA and do a manual sample using ADC API I get the correct values.
/* Variable declarations for DMA */
/* Move these variable declarations to the top of the function */
uint8 DMA_Chan;
uint8 DMA_TD[1];
/* DMA Configuration for DMA */
#define DMA_BYTES_PER_BURST 2
#define DMA_REQUEST_PER_BURST 1
#define DMA_SRC_BASE (CYDEV_PERIPH_BASE)
#define DMA_DST_BASE (CYDEV_SRAM_BASE)
DMA_TD[0] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_TD[0], 2, DMA_TD[0], 0);
CyDmaTdSetAddress(DMA_TD[0], LO16((uint32)ADC_SAR_WRK0_PTR), LO16((uint32)RSSI_Val));
CyDmaChSetInitialTd(DMA_Chan, DMA_TD[0]);
CyDmaChEnable(DMA_Chan, 1);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It would be much easier for me to get hands on your (not-)working project, so I could adapt it to my hardware (-050 board) and test it.
Can you just reduce your project to the barest and upload it?
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bob,
Cut down project attached.This locks up in main loop.
What I need is the ADC obtaining data continuously and poking result via DMA into the "signal Level" variable.
The aim is to capture the level sample as close to the specific time in my code possible.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content