I have generated 2-PPM signals with software using PIC microcontroller, which actually looks like VPPM with 50% duty cycle, and my next step is controlling the pulse-width of the 2-PPM signals. Is there any way to control it with software?
since you might use a PWM generator (belonging to the periphery of the PIC) in order to relieve the software, and its details could depend on the type of PIC, could you please give the name of your PIC?
I'm using PIC16F877A and it contains a PWM mode in CCP module. In PWM mode, microcontroller can produce up to a 10-bit resolution PWM output. What I must do is to modulate serial binary data with VPPM. Thus I will need a pulse-width controlled system. In the figure, you can see how the waveforms should look like.
Use both CCP modules in Compare mode. One CCP module, say CCP2, has register CCP2CON = 0b1011, so a compare match resets Timer1. Therefore, the content of register CCPR2 determines the period T.
The other CCP module, CCP1, has register CCP1CON = 0b1000 (set output on match) or CCP1CON = 0b1001 (clear output on match). In the first case ("1") the content of CCPR1 determines the duration of the pause, in the second case ("0") the content of CCPR1 determines the duration of the pulse.
The main problem of this solution seems to be that in any case the switching between 0b1000 and 0b1001 had to be done after the match of CCPR1 (and the output edge) within the period but in case of two consecutive equal values (two "0" or two "1"), the switching must occur as exactly as possible at the border between two periods because each switch forces the output pin to the state before the match, i.e. 0b1000 forces the output to "0", and 0b1001 forces the output to "1".
If the period T is large and the minimum duration of pulses and pauses is not less than, say, 100 machine cycles, one might do the switching in the interrupt service routine for CCP2IF but gets the latency of the interrupt as penalty. A faster reaction can be had with exclusive polling but since the software will have additional tasks, a hybrid solution might be best:
If you can configure and start Timer2 in such a way that its period equals the period of Timer1 (+CCP2) and that its compare match (and reset) occurs not less than 10 machine cycles before the reset of Timer1 (for testing, generate two output signals), then the reset of Timer2 can trigger an interrupt, and in the respective interrupt service routine you can do the polling for the CCP2IF flag. Then you can write the new value to CCP1CON and the appropriate values to CCPR1H and CCPR1L, prepare the 3 values for the next interrupt, and return from the interrupt routine.
The function which determines the PWM value should provide both the value for the pulse width W (for the case "0") and the value for the pause width T - W (for the case "1").
I cannot imagine a less awkward solution using PWM mode.
At first thank you Joerg Fricke for the information.
Since the compiler cannot compile some of code blocks because of the hardware limitations, I started looking new microcontrollers which have more capable timers etc.
I'm amazed because there should be no problems with using all the onchip peripherals simultaneously, and the source code for controlling the CCP modules (and perhaps Timer2) will be considerably shorter than my colloquial description of it.
Does the rest of your software nearly fill the 8 kInstructions program memory?
After long efforts, I was able to get the waveform I wanted. For now I can control the pulse-width with 3-bit resolution. In the figure, there is an output waveform with 80% duty cycle for sample binary data array.
because this seemed to me a nice problem in view of the apparent absence of complete hardware solutions in microcontrollers, I tried it myself, using a PIC16F877A clocked at 20 MHz => machine cycle frequency of 5 MHz.
Details I found:
- Since the interrupt latency is less than 4 machine cycles = 800 ns, my idea to reduce the latency by an interrupt of Timer2 and subsequent polling is unnecessary. (However, please see my next contribution.)
- Because the deviation of the pulse duration due to the latency is systematic (duration too long (+905 ns) at "1" followed by "1", too short (-905 ns) at "0" following "0") it can be easily compensated by adjusting the pulse resp. pause duration; in the present case, by adding 4 (or 5) to the compare value for the pause duration of "1", and adding 4 (or 5) to the compare value for the pulse duration of "0".
- In order to get a fast reaction to the CCP2 interrupt, it seems best first to switch CCP1 into the off-mode; then the data latch for RC2 determines the output, and this data latch can be set / reset beforehand.
- After the reset of Timer1 at the end of each PWM period, CCP1 is working properly again after completion of the seventh instruction (movwf CCP1CON) in the interrupt service routine. Please see the attached source code. So, with 4 cycles latency and the compare match occuring in the cycle after the seventh instruction at the earliest, the PWM pulses and pauses must not be shorter than 4 + 7 + 1 = 12 machine cycles = 2.4 us. In case it becomes necessary to save the content of the registers W and STATUS at the beginning of the ISR, the minimum duration would increase to 4 + 10 + 1 = 15 cycles = 3.0 us.
In order to get easily readable oscilloscope screens, I used a period of 200 us while in reality the period is more likely a few ms long (if the emphasis is on well resolved PWM, and not on high data rate). For the same reason, I used a constant pulse width of 50 us, and a constant binary information of 0xCC. In the first attached picture, we see the transmission of the binary information (0, part of) 1 1 0 0 (1, part of). To have control of the details I wrote the test program in assembler.
Result: Two adjacent pulses (1 followed by 0) have a duration of 100 us (no deviation at all). The "0"-pulses (second 0 in "00") are about 105 ns too short, and the "1"-pulses (first 1 in "11") 105 ns too long. With a PWM period of, say, 5 ms this would amount to a relative deviation of +/-21 ppm. I guess this is tolerable in almost all applications.
Since the clock frequency of Timer1 is 5 MHz, a PWM period of 5 ms would result in 25000 timer steps per period; so, in this case the PWM resolution would be better than 14 bit. For a resolution of 10 bit, a period of at least 204.8 us + 2 * 3.0 us = 210.8 us is necessary, resulting in about 4743 bit/s.
If a high bit rate is the main priority, then TMR1H remains always 0 which cuts down the time of the ISR (including saving and restoring W and STATUS) to 35 cycles = 7 us. Based on the PIC16F877A, a reasonable upper limit seems to be a bit rate of more than 68 kbit/s with a PWM period of 14.6 us = 73 machine cycles, 48 different PWM values, and a duty cycle in the range 17.8% .. 82.2%. The second picture shows the signal behind a low pass filter (R = 1kOhm, C = 100nF), Vss = 3.38 V at VDD = 5 V; the PWM value is just counted up and down for demonstration.
I guess this bit rate should be sufficient for the transmission of mp3 or AAC encoded audio signals (1 channel) in good quality, provided there isn't much overhead due to protocols on any higher layers.
sorry, I don't want to strip you of all the fun ;-) but it's such a pretty and limited problem, and I wasn't satisfied with a PWM variation of 65% of the supply voltage, so I couldn't resist to go one step further:
Now T2 is really the source of the interrupt but instead of polling the T1 reset, the ISR itself resets T1 by its 4th instruction (CCP2 is unemployed now). This guarantees that T1 and T2 run synchronously for arbitrary duration, and permits a minimal pulse width of 1.2 us. Thus, with T = 14.6 us, f > 68 kHz as before, now 62 PWM values (nearly 6 bit) are possible, and the PWM range is about 84% of the supply voltage (about 8% .. 92%, please see the attached picture, I guess the measured 87% are due to noise).
I think the simplest way to receive the data to be transmitted and the PWM values is the use of one or two of the serial interfaces. I feel SPI for the data (together with a "buffer full" output signal) and asynchronous receiver for the PWM values would work well.
Limitations are that no additional interrupt must be used, and that the receiving process has to be divided into blocks (
Thank you for information and your efforts Joerg Fricke
I don't have any VPPM demodulator and I'm currently working on the transmitter (modulator) side. So the challenge is that there is no real hardware for VPPM. However, there are many papers about VPPM, but none of them went beyond theory.
I seldom used PIC MCUs with the exception of the dsPIC family so I don't have a good overview of these families. Now I was surprised to find that there are PICs containing some "Configurable Logic Cells" (CLC), similar to CPLDs.
It is always possible to implement a customized MCU using an FPGA, of course, but with considerable effort or with notable costs (buying the VHDL description of a processor). But these PICs provide an inexpensive solution with a certain degree of adaptability even of the hardware.
I found this sufficiently intriguing to treat myself to a late christmas gift in the form of a few PIC16F1705. I guess a VPPM generator based on one of these will provide an even better performance with less software challenges. I will keep you informed.
BTW, could you please outline the performance you are aiming at? According to your project, you are striving to transmit audio by VPPM. Would you be satisfied with the performance I described in my previous answer (68 kbps, PWM range 8% to 92%), or if not, which parameter(s) should be improved?
since you haven't yet answered my question I don't know if my suggestions are below or above your expectations and needs.
Anyway, I found that the PIC16F1705 is able to generate VPPM signals (with static parameters) exclusively by hardware (please see the attached file CLCSch.jpg). Beside the configuration task, the software is still neccessary to transfer the data, of course.
Clocked by 32 MHz (=> system clock 8 MHz), the minimum pulse (or pause) width is nominally 125 ns. In fact, the pulses of any duty cycle and of both single width and double width are 4.1 ns shorter than their nominal value. I guess this deviation can be neglected.
For a PWM demo I chose a PWM value range of 0 .. 99 corresponding to a duty cycle of 1/101 to 100/101, and a period T = 101 system cycles = 12.625 us, resulting in more than 79 kb/s. Please see the attached screen shots (in the first two, channels 1 (yellow) and 4 (red) are PWM signals generated by CCP1 resp. CCP2 (on output pins just for debugging), channel 2 (green) is the VPPM signal) and the source code. If you have any questions, please ask.
For the reception of the bit stream to be transmitted, I would use SPI in master mode (this renders even the "buffer full" handshake signal mentioned earlier unnecessary), for the PWM values Rx of the UART modul. In my Init routine, the I/O pins are already configured for this purpose.
For more demanding tasks, I would choose the PIC18F47Q43 (or a similar member of this family), it is inexpensive, too, provides 8 CLCs, even DMA (never before did I find this feature in an 8-bit MCU), and permits clock frequencies up to 64 MHz.
PS. I just received some PIC18-Q43 ordered from a distributor, and found a notice by Microchip telling me that these are engineering samples intended for evaluation, not for production, at present not tested over the full temperature range.
But I think that's no problem in the framework of prototyping because in most cases we can provide the means to keep the circuits at or near room temperature.
still not knowing where you are heading, I had a look at the IEEE Standard 802.15.7. The only operating modes with pure VPPM are in PHY I and PHY II. PHY II with optical clock rates of several MHz is obviously beyond the ability of any PIC controller, so PHY I remains, with an optical clock rate of 400 kHz.
With a period of 2.5 us, and provided the ISR I wrote cannot be considerably shortened, a PIC16F1705 with a 32 MHz clock is obviously too slow.
As transmitter, I would use a PIC18F47Q43 with an external crystal oscillator of 64 MHz => minimum pulse width 62.5 ns, 39 PWM values, duty cycle from 1/40 to 39/40. (However, the standard prescribes a PWM resolution of 0.1 % in view of the logarithmic sensitivity of the eye but limits the range used for data transmission using VPPM to 10% .. 90%. Accordingly, levels lower than 10% and higher than 90% could only be reached by inserting dark or glaring intervals carrying no information; in the same way, a higher resolution could be achieved.)
As receiver, a PIC18F47Q43 could be clocked by its internal oscillator of 64 MHz. These MCUs contain a Signal Measurement Timer (SMT) which can measure the pulse width and the pause width of a signal continuously. I would clock the SMT by an external crystal oscillator of 50 MHz. On one hand, this results in about three clock periods per minimum pulse width (seems a reasonable value to me), on the other hand the timer values will never exceed 250 so handling these 8 bit values is fast and easy.
I know that at present you are not concerned with the receiver but since this seems to be an experimental project I guess that you are expected to present a working system in the end.