LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How to generate a signal with ask modulation?

Hi folks!

I'm trying to plan how I would go about generating a signal with ASK modulation;

My current setup:
LabWindows/CVI 8.1
NI USB-6251 DAQ
NI-DAQmx driver

I want to generate a signal from a 57bit long bit pattern. The signal is in Manchester code, ie. a 0 is presented as a transition from 1 to 0 and a 1  is presented as the opposite. The carrier signal is a 125kHz sin wave.

One way of generating this signal would be to set up a large buffer and fill it with "sin wave blocks" and zero values. Looping through the bit pattern to fill the buffer. And write the whole thing out via DAQmxWriteAnalogF64.. I don't like this solution, seems a bit clumsy to me.

When I was over in UK for LabWindows/CVI course I got a tips to use a counter in combination with a continuous 125kHz sin signal. I think the idea was to set up the counter as clock for the sin wave and write the bit pattern to the counters gate. This would make the clock stop when the bit pattern was 0 resulting in the continuous sin wave beeing "paused".. Any ideas for this one, how would I set something like this up in code?

Currently I'm generating a digital pulse with the correct baud rate in an array, routing it out via AO on the 6251 through the gate on a external signal generator (set to 125kHz sin), this works ok but I would rather drop this extra piece of hardware and manage with just the USB device..

Could anyone please guide me in the right direction here, I don't think the NI USB-6251 has a pause trigger?

I'll attach some images to (hopefully) illustrate my inadequate English 😛

The original bit pattern, it consists of 16 bits of zeros, 9 bits of custom sync pattern, then two blocks of 16 bits data (0x5A5A and 0xABAA)


This is the bit pattern divided into chips ( "half bits" ), ignore the sync pattern as it violates the Manchester standard


This is "one building block" from which the ASK pattern is generated, this represents a zero (transition from 1 to 0)


This is the resulting ASK pattern


Please ask me to clarify if any of this is unclear 🙂

---
Best regards
Peder Schmedling
0 Kudos
Message 1 of 5
(4,834 Views)

Hey Peder,

This is a great post - the pictures are a huge help. I've worked with encoding schemes like this before (AM modulation for IRIG-B, simulating RFID) and for me the easiest has always been to just use software to generate your waveforms and then just output it. I usually end up writing a VI/function that generates the analog waveform based on whatever bit pattern I need and writing that with the DAQmxWrite. You pretty much already have the foundation for that with your building block.
That being said, you could generate it by manipulating the clock, though I think it will be more haste and tie up more resources. Let me address a couple of you comments:

" I don't think the NI USB-6251 has a pause trigger?" - The 6251 (USB and PCI are essentially the same) does support a pause trigger. You could use it to gate your AO sample clock - if you can generate the digital signal required. This digital signal would essentially be the bit pattern in your post.

To implement the pause trigger, you'd want to start with the "ContGen-IntClk.prj" example and set the properties needed to implement a pause trigger:
...
        DAQmxErrChk (DAQmxCfgSampClkTiming(gTaskHandle,"",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
        // configure pause trigger
        DAQmxErrChk (DAQmxSetTrigAttribute (gTaskHandle, DAQmx_PauseTrig_Type, DAQmx_Val_DigLvl));
        DAQmxErrChk    (DAQmxSetTrigAttribute (gTaskHandle, DAQmx_DigLvl_PauseTrig_Src, "PFI0"));
        DAQmxErrChk    (DAQmxSetTrigAttribute (gTaskHandle, DAQmx_DigLvl_PauseTrig_When, DAQmx_Val_High));
       
        DAQmxErrChk (DAQmxRegisterDoneEvent(gTaskHandle,0,DoneCallback,NULL));

...
"I think the idea was to set up the counter as clock for the sin wave and write the bit pattern to the counters gate." You could do this with a counter, our you could just pause trigger the AO sample clock (which is essentially a counter reserved for AO).

The question becomes, where does the bit pattern come from? If you already have it externally, then you're pretty much set and it would be a clean solution.  If not, the only HW timed way to do it onboard would be to use the clocked DIO on the 6251. This would require one of the onboard counters for the clock, and physically connecting the digital output signal to a PFI pin. You would need to ensure that the AO generation is synched with the bit pattern too, but you should be able to do that with a start trigger. You would also have to construct the digital pattern in SW, which for me if you going to go that far you might as well go the extra step and turn that into an analog signal. Let me know if you think you want to pursue that route and need some tips - it would require 3 tasks.

Hope this helps, feel free to post your code when you get it up and running.

Andrew S
National Instruments

Message 2 of 5
(4,797 Views)

Hey Peder,

This is a great post - the pictures are a huge help. I've worked with encoding schemes like this before (AM modulation for IRIG-B, simulating RFID) and for me the easiest has always been to just use software to generate your waveforms and then just output it. I usually end up writing a VI/function that generates the analog waveform based on whatever bit pattern I need and writing that with the DAQmxWrite. You pretty much already have the foundation for that with your building block.
That being said, you could generate it by manipulating the clock, though I think it will be more haste and tie up more resources. Let me address a couple of you comments:

" I don't think the NI USB-6251 has a pause trigger?" - The 6251 (USB and PCI are essentially the same) does support a pause trigger. You could use it to gate your AO sample clock - if you can generate the digital signal required. This digital signal would essentially be the bit pattern in your post.

To implement the pause trigger, you'd want to start with the "ContGen-IntClk.prj" example and set the properties needed to implement a pause trigger:
...
        DAQmxErrChk (DAQmxCfgSampClkTiming(gTaskHandle,"",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
        // configure pause trigger
        DAQmxErrChk (DAQmxSetTrigAttribute (gTaskHandle, DAQmx_PauseTrig_Type, DAQmx_Val_DigLvl));
        DAQmxErrChk    (DAQmxSetTrigAttribute (gTaskHandle, DAQmx_DigLvl_PauseTrig_Src, "PFI0"));
        DAQmxErrChk    (DAQmxSetTrigAttribute (gTaskHandle, DAQmx_DigLvl_PauseTrig_When, DAQmx_Val_High));
       
        DAQmxErrChk (DAQmxRegisterDoneEvent(gTaskHandle,0,DoneCallback,NULL));

...
"I think the idea was to set up the counter as clock for the sin wave and write the bit pattern to the counters gate." You could do this with a counter, our you could just pause trigger the AO sample clock (which is essentially a counter reserved for AO).

The question becomes, where does the bit pattern come from? If you already have it externally, then you're pretty much set and it would be a clean solution.  If not, the only HW timed way to do it onboard would be to use the clocked DIO on the 6251. This would require one of the onboard counters for the clock, and physically connecting the digital output signal to a PFI pin. You would need to ensure that the AO generation is synched with the bit pattern too, but you should be able to do that with a start trigger. You would also have to construct the digital pattern in SW, which for me if you going to go that far you might as well go the extra step and turn that into an analog signal. Let me know if you think you want to pursue that route and need some tips - it would require 3 tasks.

Hope this helps, feel free to post your code when you get it up and running.

Andrew S
National Instruments

0 Kudos
Message 3 of 5
(4,793 Views)
Thank you very much for your reply stilly32, especially on the pause trigger 🙂

Sorry for not mentioning where the bit pattern comes from, it's generated from 16 + 9 bits of predefined bits and 2 x 16bits of input (through the GUI of my app.) from the user. So the easiest way to the target here is to generate a waveform pattern in memory and output it via DAQmxWrite. This is also what I'm currently doing in my v2 of the app. (v1 = bit pattern gated through external signal generator, v2 = waveform directly out on AO on the USB-6251).

This works ok for now, but I may require a more sophisticated solution as I'm implementing functionality to adjust the resolution of the generated waveform. I'm running into problems when I configure the timing of my task; when I use DAQmxCfgSampClkTiming and set the rate to more than 1MHz, the function returns a warning number 200040 (DAQmxWarningSampClkRateViolatesSettlingTimeForGen). Does this mean that the USB-6251 has reached it's limit? Any chance of reaching a higher sample rate by using the "counter metod"?

I'm letting the user set the number of samples to use per. Sin cycle. I'll try to show the calulation:

Constans:
Datarate: 3906 bit/s
ASK frequency: 125kHz
Total bits to transmit: 57
Cycles per bit: 125kHz / 3606 ~ 32

8 samples per Sin cycle:
Total samples: cycles per bit * samples per cycle * bits to transmit = 32 * 8 * 57 = 14592
DAQ sample rate: samples / sec = total samples / ((1 /
datarate) * bits to transmit)   = 14592 / ((1 / 3906) * 57) ~ 999936 ~ 999.9kHz

9 samples per Sin cycle:
Total samples: cycles per bit * samples per cycle * bits to transmit = 32 * 9 * 57 = 16416
DAQ sample rate: samples / sec = total samples / ((1 /
datarate) * bits to transmit)   = 16416 / ((1 / 3906) * 57) ~ 1124928 ~ 1.1MHz


I figure if I use AO in continuous mode I would be able to fill the buffer with a Sin wave pattern of 1000 samples with ease...? Then by using a pause trigger I would be able to reach much higher resolution... any thoughts?
---
Best regards
Peder Schmedling
0 Kudos
Message 4 of 5
(4,780 Views)

Hey Peder,

The real limit on your resolution is going to be the max sample rate of the analog output- which is ~2.8MS/s. That warning (200040) is referring to the Settling time spec in the specs. For a full scale step (going from -10 to 10) it would take 2us to fully settle. If I recall right, DAQmx won't throw a warning at 500k because error caused by the settling time doesn't factor in much when compared to the AO accuracy untill >1MS/s (don't quote me on that Smiley Happy  ). This is for a full scale swing - for a continuous sine wave you can pretty much ignore that error.

The theoretical max resolution that you'll be able to generate a 125k sine wave would be 2.8M/125k = 22.4 - so 22 samples per cycle at 2.75M. The issue you'll run into there is that the AO sample clock is a divide down of the 20MHz sample clock - and 2.75M is an not an integer divide down. You can work with this though. If you want a closer frequency, you can use a counter (which divides from the 80Mhz clock) as the clock for your AO - that will give you a 4 times the clock resolution and a clock rate closer to 2.75M. There's more you can do, such as finding the attainable samples rates and working backword from there, but you should be able to get close enough just using the AO sample clock or a counter.

Hope this helps,

Andrew S

0 Kudos
Message 5 of 5
(4,772 Views)