VHDL code for pulse signal with variable working cycle - controls

I need to create a VHDL code for this situation:
**Draw a control circuit that generates a pulse signal with:
fixed working frequency (100 KHz)
variable working cycle
The phase difference should be increased or decreased by the direction of the spin of a rotary control of 8 bits.**
Additional info:
D = t (on) / T
D = working cycle
t (on) = Time the activated signal lasts (rotary control of 8 bits)
T = signal period (constant)

You seem to be wanting to generate a mark:space ratio of between 1:255 and 255:1, so you will need a clock frequency of 256 * 100kHz.
An 8 bit incrementing counter can be left free-running clocked at that rate.
Now have a flop that is SET when the counter overflows from X'FF to X'00 and that CLEARS when the timer value makes the transition from N-1 to N. Where N is the 8 bit value on your duty cycle setting control and controls the width of the mark.
The threshold controlled flop's output is your variable duty cycle 100kHz.

Related

GPIO32 pin works in analog mode, always reads 0 in digital mode

I'm having some difficulty getting PCNT pulse counting working with a prototype ESP32 device board.
I have a water level sensor (model D2LS-A) that signals state by the frequency of a square wave signal it sends to GPIO32 (20Hz, 50Hz, 100Hz, 200Hz, 400Hz).
Sadly, the PCNT counter stays at 0.
To troubleshoot, I tried putting GPIO32 in ADC mode (attenuation 0, 10-bit mode) to read the raw signal (sampling it many times a second), and I'm getting values that I would expect (0-1023). But trying the same thing using digital GPIO mode, it always returns 0, never 1 in all the samples.
Since the PCNT ESP IDF component depends on reading the pin digitally, the counter never increments past 0.
So the real problem I'm having is: why aren't the ADC readings (between 0-1023) translating to digital readings of 0-1 as one would expect?

How to control servos continously using Bascom 8051

I want to control the movement of a servo using Bascom 8051 continuously so that it could change positions.
I've tried using brute force by assigning the pulse length manually and changing it after a certain delay.
P1.2 = 1
Config Servos = 1 , Servo1 = P1.2 , Reload = 10
Enable Interrupts
Do
Servo1 = 15 '90 degrees to the left
Wait 10
Servo1 = 65 '90 degrees to the right
Wait 10
Loop
End
I expect the servo to switch positions back and forth but all it does is stuck in one place.
There are two different BASCOM variants, depending on your microcontroller. You have tagged both so it is not clear which one you mean. Also you didn't tell us which servo you are using.
Anyway, the inner workings are similar enough to try to answer your question.
First we need to understand which kind of signal a standard R/C servo expects. The servo position is coded in the width of a (positive) pulse. It ranges from 1 ms to 2 ms. This pulse has to be repeated every 20 ms that is a repetition frequency of 50 Hz.
With Config Servos you set up a timer as an interrupt source and its service routine. That means that the pulses for the servo(s) are generated automatically without any further action by your main program. You just need to set the desired pulse width in the assigned variable; this actually depends on the BASCOM variant. For AVR its an array Servo(1) = # and for 8051 there are individual variables Servo1 = #.
According to the manual(s) the parameter Reload sest the resolution in µs of the values for the pulse width. You chose 10.
So for the range of pulse widths you need to assign values between 100 and 200 to the servo variable:
Do
Servo1 = 100
Wait 10
Servo1 = 200
Wait 10
Loop
Additional note: The manual for BASCOM AVR mentions the port mode to set. The pin used for the pulse has to be made an output.

Multiple PWM Channels on PIC

I use the PIC16F88 for my project, with XC8 compiler.
What I'm trying to achieve is to control 4 LEDs with 4 buttons, when you press a buttons it increases the duty cycle of the corresponding LED by 10%.
When you press the button on RB0 it increases the duty cycle of the LED on RB4, and so on.
Every LED is independent, therefore it can have a different duty cycle.
The problem is that the PIC i'm using only have one PWM module on either RB0 or RB3 (using CCPMX bit).
After some research I decided to implement software PWM to have four different channels, each channels would control one duty cycle, but most of the sources I found didn't provide any explanation on how to do it.
Or is there a way to mirror PWM to multiple pins ?
Thanks by advance for helping me out.
Mirroring is not an option.
PWM is relatively simple. You have to set PWM frequency (which you will not change) and PWM duty cycle (which you need to change in order to have 0-100% voltage range). You have to decide about resolution of PWM, voltage step that you need (built in PWM for example is 8-bit and has 0-255 steps).
Finally, you have to set timer to interrupt based on PWM frequency * PWM resolution. In Timer ISR routine you need to check resolution counts and PWM value of all your channels. Resolution count will have to reset when resolution value is reached (and start to count from 0 again, all outputs go HIGH here, also). When PWM value of output is reached you have to toggle (pull it LOW) corresponding pin (and reset it back to HIGH with every resolution count reset).
This is only one way of doing it, involves only one timer and should be most simple since your PIC is low with resources.
Hope it helps...

Use DCM for generate clock of 78 mhz from 100 mhz clock

I have a clock of 100 mhz. I want to use DCM to create a clock of 78 mhz.
I think I should use two DCM, where the output of first DCM goes into the second DCM but I don't know if this will work.
Best Regards
Rather than using a DCM directly you can investigate using a Direct Digital Frequency Synthesizer (DDFS). It amounts to an accumulator that is incremented by a constant count value. You can control the precision by the size of the accumulator.
It is helpful if there is as much disparity between the accumulator clock and the generated frequency as possible. Consider using a DCM to scale the 100MHz up to the highest speed you can run a counter of the necessary width and still meet timing for your target device. There will be some jitter equal to one period of whatever clock is driving the accumulator but the average frequency can be made very close to 78 MHz.
accum_freq = 100 MHz * DCM_MULTIPLIER
accum_size = ceil(log2(accum_freq / (78 MHz * tolerance)))
increment = 78 MHz / accum_freq * 2**accum_size
accum = accum + increment
You then tap off the MSB of the accumulator to get your synthesized 78 MHz clock.
You can either manually compute these constants for use as magic numbers or do the arithmetic natively in VHDL to define the size and increment as machine computed constants. By reducing the tolerance you will increase the required size of the accumulator. Start off with 0.01% (0.0001) and see if it is satisfactory.
What device are you targeting? On a Spartan-6 the DCM_CLKGEN allows a multiplier of 39 and a divider of 50, which gets you your 78MHz.
If you set your multiplier to 7 and your divider to 9 you'll be able to get to 77.77 MHz. Will that work for you?

Frequency divider by any integer 1-16

I have implemented a frequency divider by the powers of 2. Now I am interested in doing a divider by any integer number from 1 to 16. Yes, I have tried but yet no ideas. How can I approach this problem?
I want to use common elements like multiplexers, flip flops and so on. Not asking for a complete solution, even though it would be great.
That is normally the job of a PLL many FPGA have some PLL on chip.
Or try a counter that resets when limit (0-15) is reached.
Each time limit is reached toggle clock.
The value for 1:1 clock needs special handling, maybe a clock bypass.
A better way would be to run the counter at double frequency to avoid the mux.
Instead of an incrementing counter a decrementing counter that loads the configured value on zero would do as well.

Resources