Like Kwinn said, this is not "PWM" as commonly understood; which refers to a pulse train of constant frequency but varying pulse width. The Stamp version is more accurately termed "PDM", pulse density modulation. Density of pulses (each of the same width in a time slot) populate almost uniformly a longer time interval (the "cycle"). This mechanism is also used for the BS2 FREQOUT command. The Parallax propeller has a similar scheme, called "duty" mode, but it has far more time slots available, each 12.5 nanoseconds wide. It's output covers a frequency range up to 40MHz and down to nearly 1/60th Hz, but the same considerations apply.
Don't use the rote example:
x = (x MIN 2000 MAX 2400)-2000*/163
You have to measure the output of the memsic over the angles that you want. Find your own minimum and maximum codes to go in the MIN and MAX conditions. Then from the full range calculate the multiplier to go after the */. I wasn't sure from your last comment that you understand that. It is really easier from the filtering standpoint to compress the range into say 200 steps from 28 to 228. Keep away from the edge cases.
I have been experimenting with one axis of the Memsic 2125 hooked to the basic stamp. Then the basic stamp feeding DAC, which is 10K resistor and .1uf capacitor. This feeds my 358 op amp configured as a buffer. I have a LED hooked to the output of the op amp. I don't have the ADC0831 hooked up after the buffer. Been experimenting by changing "duty" numbers in the PWM code. x=(x MIN value MAX value)-MIN value, times scale constant. Only using positive values of x. I can dim the LED with various duty values in the PWM command. I used a volt meter to determine the exact analog voltage output, as the brightness of a LED cannot determine exact voltage. Using the volt meter, from the output of the op amp I got a good range of volts from 3.5 volts down to almost nothing. When I hooked the volt meter to the Vss side of the LED I would get a range from 1 volt down to almost nothing. This one volt range was "more" controllable and consistent with tilt. This led me to believe my duty range was somehow wrong concerning the 3.5 volts to zero. I tried putting various values in the MIN and MAX, thinking it might work better with the approximate 15 degree angle of operation. I soon discovered that there is 'a million and one' possible values for MIN and MAX.
It was at this point I went to Tracy Allen's suggestion: "It is really easier from the filtering standpoint to compress the range into say 200 steps from 28 to 228. " That did not tell me much, because this range has to be in the 1875 to 3125 range scaled down.
I got somewhat confused when Tracy Allen used */ operator for the scale constant, instead of the ** . In Tracy's example x=(xMIN 2000 MAX 2400)-2000*/163. Finally figured out where the 163 came from as 400x163/256=254 which winds up being 254 when you figure it being all of the 400. I could not follow Tracy Allen's tip on how to factor =65535/ (full scale range). This whole scaling thing seems in some way like new math to me. So I used "OLD MATH" to figure it out. 400x41615/65536=253.99. So at this point I got stuck trying to figure out Tracy's suggestion of getting the range in 200 steps between 28 and 228. You still have to decide on a MIN and MAX value before you can scale. In trying different MIN and MAX with the numbers 28 and 228, I did not get any better controllable voltage results. When I say better, better than, I mean when I used x= (x MIN 1875 MAX 3125)-1875 **13369
It appears I do not have a handle on how to figure MIN and MAX to get better control. There seems to be several things to take into account to arrive at a controllable voltage in a desired range. First the MIN MAX, and scale constant in the duty. Next the number of cycles, and finally the values in the DAC filter circuit. Thus far the duty part of PWM seems to cause the most dramatic changes in output voltage reactions. I keep asking myself "WHY" does this have to be so difficult? How can I come up with a more controllable MIN MAX and scale range? One other thing: If the tilt reaction is opposite of what you want, can you simply insert a minus in the code and make things reverse? Like: x=(x MIN 2000 MAX 2400)-2000*163-400?
Publison, sorry about my post. I am trying so hard to get this Memsic 2125 working.
Here is my problem in simple terms: I don't understand Tracy Allen's last post where he says: "It is really easier from the filtering standpoint to compress the range into say 200 steps from 28 to 228. Keep away from the edge cases." I understand the 200 steps, but not the 28 to 228.
This is what is being discussed: x =(x MIN value MAX value)-MIN value times the scale constant. You must get MIN and MAX value correct, in relation to scale constant, to produce a usable range analog range of voltage with a DAC.
The Memsic reads values from 1875 to 3125, so you can put those or different numbers in. You then can use different scale values. I know how to scale. I can't figure out what MIN, MAX and scale to better control the Memsic in obtaining a analog voltage range. I have tried all kinds of number and scale combinations.
I edited your comment to be more readable. This is the white space I was talking about.
I certainly am capable of not doing such thing, it does make easier to see on a small screen like mine. Everything just kinda jumbles together sometimes.
Do you have a resistor in series with the LED at the output of the op-amp?
Using the volt meter, from the output of the op amp I got a good range of volts from 3.5 volts down to almost nothing.
If you want it to go to 5V full scale with an LM358 op-amp, you will have to supply it (the op-amp only) with at least 7 volts Vdd.
It appears I do not have a handle on how to figure MIN and MAX to get better control.
Position your memsic at your desired endpoint tilt to the left and record the reading from the debug screen, then do the same for your desired maximum endpoint tilt to the right. Those are the numbers that figure into the MAX MIN and scaling equation. If you do that and come back at me with some numbers, then I will show you how to work them in using either old or new math. But you have to give me those numbers first!
Yes, please, do work on the empty space between your thoughts!
Publison, thanks, I see what you mean now, and will start using white space.
Thanks for trying to help Tracy, I will try to answer your responses.
Yes, I have a resistor in series with the LED.
Not interested in going to 5 volts, but I do know how to create gain with an op amp. The 3.5 range I got jumped to quick to lower numbers, and was not a gradual change down to almost no volts. The quick jump made it unusable.
Tracy I will try to get you some MAX MIN end point numbers, but it may be this next week.
The only thing that seems to be getting close is the following: x =(x MIN 1875 MAX 3125)-1875 */120 I keep everything but the */120 the same. I am constantly changing the value of */ I have not got it perfect yet but it is working better than any other thing I have tried. I have a meter hooked up, so I can see the voltages as I change the */ values.
There are several things that need to be considered if you want to control the brightness of the LED over the full range of intensity. The best place to start is at the LED and work backwards from there.
Lets assume we have a red LED with a forward voltage of 2.2V and want a maximum of 20mA current. Vdd is 7.0 volts so the LM358 output can go to 5.0 volts.
The LED requires 2.2V before any current flows, so the maximum voltage across the resistor will be 2.8V.
To get 20mA the R2 needs to be 2.8/0.02= 140 ohms.
The output voltage of the PWM/RC circuit and opamp needs to start at 2.2V and go up to 5.0V to produce a current output that starts at 0 and goes up to 20mA.
The PWM instruction needs to output a signal that produces an output from the RC filter that goes from 2.2V to 5.0V. The duty value is calculated by 2.2x256/5=112.64, so 113 is the nearest integer value to produce a 2.2V output. For a 5.0V output the duty value would be 255.
To cover the desired voltage and current range for the LED the MIN/MAX input from the memsic must be converted to a 113 to 255 range for the duty parameter of the PWM instruction on the BS2. The desired range would be 255 – 113 = 142. The offset would be 113.
The input range from the memsic is 1250, and the desired output range to the PWM instruction is 142, so the range factor would be 142 x 65535 / 1250 = 7445, which would make the calculation:
x= (((x MIN 1875 MAX 3125)-1875)**7445) + 113
Kwinn said it well, but I'll just add a note about the */120 value. You said,
...keep everything but the */120 the same. I am constantly changing the value of */ I have not got it perfect yet but it is working better than any other thing I have tried.
There is no great mystery about what you should get from the op-amp output. Detach the LED so there is no load on the op-amp output. 5 volts supply * 120 / 256 = 2.34 volts. You say you have a 10k resistor and a 0.1µF capacitor at the input of the op-amp, time constant = 1 millisecond, so that is about 100 times the PWM period (1/100kHz). Check. The output is less than the 3.5V maximum when the LM358 is powered from 5V. Check. If you see anything much different than 2.34V, there is something wrong with the way the circuit is hooked up.
If I were you, I'd increase the resistor to 100k and the capacitor to 1µF. That would be a 0.1 second time constant and would allow better, ripple-less readings when you go to the lower PWM duty parameters.
Tracy Allen and kwinn, I appreciate your help. I feel really stupid, because I just realized something simple. I have two different voltage controlled amplifier ICs I use. One operates from 0 to 1 volt, and the other operates from 0 to 4 volts. This whole effort was to get the Memsic, Basic Stamp, and op amp to produce the above analog voltage ranges, to be used with the voltage controlled amplifier ICs I use. I thought using the LED would be a visual aid, but because of it's load, it messes up the voltage level measurements.
I was able to get a good 0 to 1 volt voltage range in testing. I was never able to get a good 0 to 4 volt range. As I said, I feel really stupid. Like trying to get blood out of a turnip. As Tracy Allen noted----the LM358---hooked up as a buffer has a output less than 3.5 volts max when powered from 5 volts. Yes, I was using 5 volts! Man-O-man how stupid can I be! No wonder I couldn't get 4 volts, when 3.5 volts was the range of the LM358 used as a buffer.
I am going to do some more bread board testing, then get back with the results. This has been like running my head against a brick wall, it felt so good when I quit! All I had to do was realize I over-looked something real simple.
Tracy, you ask for the tilt end point numbers. 2546 to 2690
I used the code below which produced a voltage range of .789 to 3.05 volts in the desired tilt movement. This is a usable range for me, using these volts to control a voltage controlled IC. For DAC filter I am using 10K and .1uf still. Using a 358 op amp as a buffer. Slight changes in the last number */209 makes big changes in voltage. Example: A change from */209, to */212 would make a big voltage range change.
I would like the range and scale constant to be less sensitive. I don't know how to reduce the range of the duty to get the stable numbers I want. I just need to improve the stability and adjust-ability while maintaining the approximate voltage range listed above.
' {$STAMP BS2}
' {$PBASIC 2.5}
'Getting analog voltage from the memsic 2125
'
[Declarations
y VAR Word
Your stated end points are 2546 and 2690, and you want to map that into a voltage of say 0V to 3V.
So, the first part of the equation should establish the range,
X = (y MIN 2546 MAX 2690)-2546
As the Memsic tilts through that range, the value of X goes from 0 to 144 proportionately. Outside that range, X sticks at either 0 on the low side or 144 on the high side. If you apply that as PWM directly to the buffer, the average voltage should go from 0 up to 5*144/256 = 2.8V. Wow, almost there.
If you want 3V on the output, it can be scaled up a bit, by a factor of 1.07. That is */ 274
X = ((y MIN 2546 MAX 2690)-2546) */ 274
So now, the upper limit is
144 * 274/256 = 154
The voltage output from the buffer is predicted to be,
5 * 154 / 256 = 3 volts.
Another way to accomplish the 3V max output is to change the offset.
X = ((y MIN 2536 MAX 2690)-2536) MIN 10
Note the change in the low limit from 2546 to 2536. The value of X now goes from 10 to 154, so the voltage is from about 0.2 to 3V. That is really a good thing from the standpoint of filtering, but can your VCA handle that?
I do see why the program you listed above came out with a voltage of 0.789 to 3.05, but, as you say, it is much much too sensitive.
Tracy, thank you so much. Your posts are helping me learn programming the basic stamp. I have had to take a break from programming due to building guitar pedals. October and November seems to be the months when people buy music stuff. I will try your example before too long. Keith
Comments
Don't use the rote example:
x = (x MIN 2000 MAX 2400)-2000*/163
You have to measure the output of the memsic over the angles that you want. Find your own minimum and maximum codes to go in the MIN and MAX conditions. Then from the full range calculate the multiplier to go after the */. I wasn't sure from your last comment that you understand that. It is really easier from the filtering standpoint to compress the range into say 200 steps from 28 to 228. Keep away from the edge cases.
It was at this point I went to Tracy Allen's suggestion: "It is really easier from the filtering standpoint to compress the range into say 200 steps from 28 to 228. " That did not tell me much, because this range has to be in the 1875 to 3125 range scaled down.
I got somewhat confused when Tracy Allen used */ operator for the scale constant, instead of the ** . In Tracy's example x=(xMIN 2000 MAX 2400)-2000*/163. Finally figured out where the 163 came from as 400x163/256=254 which winds up being 254 when you figure it being all of the 400. I could not follow Tracy Allen's tip on how to factor =65535/ (full scale range). This whole scaling thing seems in some way like new math to me. So I used "OLD MATH" to figure it out. 400x41615/65536=253.99. So at this point I got stuck trying to figure out Tracy's suggestion of getting the range in 200 steps between 28 and 228. You still have to decide on a MIN and MAX value before you can scale. In trying different MIN and MAX with the numbers 28 and 228, I did not get any better controllable voltage results. When I say better, better than, I mean when I used x= (x MIN 1875 MAX 3125)-1875 **13369
It appears I do not have a handle on how to figure MIN and MAX to get better control. There seems to be several things to take into account to arrive at a controllable voltage in a desired range. First the MIN MAX, and scale constant in the duty. Next the number of cycles, and finally the values in the DAC filter circuit. Thus far the duty part of PWM seems to cause the most dramatic changes in output voltage reactions. I keep asking myself "WHY" does this have to be so difficult? How can I come up with a more controllable MIN MAX and scale range? One other thing: If the tilt reaction is opposite of what you want, can you simply insert a minus in the code and make things reverse? Like: x=(x MIN 2000 MAX 2400)-2000*163-400?
Your post are really hard to read.
You need more white space, (paragraphs), or break them up into separate threads.
Sorry, but it is a forum courtesy to make them readable, otherwise other people, and myself will not spent the time reading them.
Here is my problem in simple terms: I don't understand Tracy Allen's last post where he says: "It is really easier from the filtering standpoint to compress the range into say 200 steps from 28 to 228. Keep away from the edge cases." I understand the 200 steps, but not the 28 to 228.
This is what is being discussed: x =(x MIN value MAX value)-MIN value times the scale constant. You must get MIN and MAX value correct, in relation to scale constant, to produce a usable range analog range of voltage with a DAC.
The Memsic reads values from 1875 to 3125, so you can put those or different numbers in. You then can use different scale values. I know how to scale. I can't figure out what MIN, MAX and scale to better control the Memsic in obtaining a analog voltage range. I have tried all kinds of number and scale combinations.
I certainly am capable of not doing such thing, it does make easier to see on a small screen like mine. Everything just kinda jumbles together sometimes.
Do you have a resistor in series with the LED at the output of the op-amp?
If you want it to go to 5V full scale with an LM358 op-amp, you will have to supply it (the op-amp only) with at least 7 volts Vdd.
Position your memsic at your desired endpoint tilt to the left and record the reading from the debug screen, then do the same for your desired maximum endpoint tilt to the right. Those are the numbers that figure into the MAX MIN and scaling equation. If you do that and come back at me with some numbers, then I will show you how to work them in using either old or new math. But you have to give me those numbers first!
Yes, please, do work on the empty space between your thoughts!
Thanks for trying to help Tracy, I will try to answer your responses.
Yes, I have a resistor in series with the LED.
Not interested in going to 5 volts, but I do know how to create gain with an op amp. The 3.5 range I got jumped to quick to lower numbers, and was not a gradual change down to almost no volts. The quick jump made it unusable.
Tracy I will try to get you some MAX MIN end point numbers, but it may be this next week.
The only thing that seems to be getting close is the following: x =(x MIN 1875 MAX 3125)-1875 */120 I keep everything but the */120 the same. I am constantly changing the value of */ I have not got it perfect yet but it is working better than any other thing I have tried. I have a meter hooked up, so I can see the voltages as I change the */ values.
Lets assume we have a red LED with a forward voltage of 2.2V and want a maximum of 20mA current. Vdd is 7.0 volts so the LM358 output can go to 5.0 volts.
The LED requires 2.2V before any current flows, so the maximum voltage across the resistor will be 2.8V.
To get 20mA the R2 needs to be 2.8/0.02= 140 ohms.
The output voltage of the PWM/RC circuit and opamp needs to start at 2.2V and go up to 5.0V to produce a current output that starts at 0 and goes up to 20mA.
The PWM instruction needs to output a signal that produces an output from the RC filter that goes from 2.2V to 5.0V. The duty value is calculated by 2.2x256/5=112.64, so 113 is the nearest integer value to produce a 2.2V output. For a 5.0V output the duty value would be 255.
To cover the desired voltage and current range for the LED the MIN/MAX input from the memsic must be converted to a 113 to 255 range for the duty parameter of the PWM instruction on the BS2. The desired range would be 255 – 113 = 142. The offset would be 113.
The input range from the memsic is 1250, and the desired output range to the PWM instruction is 142, so the range factor would be 142 x 65535 / 1250 = 7445, which would make the calculation:
x= (((x MIN 1875 MAX 3125)-1875)**7445) + 113
If I were you, I'd increase the resistor to 100k and the capacitor to 1µF. That would be a 0.1 second time constant and would allow better, ripple-less readings when you go to the lower PWM duty parameters.
I was able to get a good 0 to 1 volt voltage range in testing. I was never able to get a good 0 to 4 volt range. As I said, I feel really stupid. Like trying to get blood out of a turnip. As Tracy Allen noted----the LM358---hooked up as a buffer has a output less than 3.5 volts max when powered from 5 volts. Yes, I was using 5 volts! Man-O-man how stupid can I be! No wonder I couldn't get 4 volts, when 3.5 volts was the range of the LM358 used as a buffer.
I am going to do some more bread board testing, then get back with the results. This has been like running my head against a brick wall, it felt so good when I quit! All I had to do was realize I over-looked something real simple.
I used the code below which produced a voltage range of .789 to 3.05 volts in the desired tilt movement. This is a usable range for me, using these volts to control a voltage controlled IC. For DAC filter I am using 10K and .1uf still. Using a 358 op amp as a buffer. Slight changes in the last number */209 makes big changes in voltage. Example: A change from */209, to */212 would make a big voltage range change.
I would like the range and scale constant to be less sensitive. I don't know how to reduce the range of the duty to get the stable numbers I want. I just need to improve the stability and adjust-ability while maintaining the approximate voltage range listed above.
' {$STAMP BS2}
' {$PBASIC 2.5}
'Getting analog voltage from the memsic 2125
'
[Declarations
y VAR Word
DEBUG CLS 'Start display
'
[Main Routine]
DO
GOSUB Memsic
GOSUB DAC
LOOP
'
[Subroutines]
Memsic:
PULSIN 7,1,y
y = (y MIN 1875 MAX 3125)-1875*/209
RETURN
DAC:
PWM 4,y,100
DEBUG HOME, DEC4 ? y
RETURN
So, the first part of the equation should establish the range,
X = (y MIN 2546 MAX 2690)-2546
As the Memsic tilts through that range, the value of X goes from 0 to 144 proportionately. Outside that range, X sticks at either 0 on the low side or 144 on the high side. If you apply that as PWM directly to the buffer, the average voltage should go from 0 up to 5*144/256 = 2.8V. Wow, almost there.
If you want 3V on the output, it can be scaled up a bit, by a factor of 1.07. That is */ 274
X = ((y MIN 2546 MAX 2690)-2546) */ 274
So now, the upper limit is
144 * 274/256 = 154
The voltage output from the buffer is predicted to be,
5 * 154 / 256 = 3 volts.
Another way to accomplish the 3V max output is to change the offset.
X = ((y MIN 2536 MAX 2690)-2536) MIN 10
Note the change in the low limit from 2546 to 2536. The value of X now goes from 10 to 154, so the voltage is from about 0.2 to 3V. That is really a good thing from the standpoint of filtering, but can your VCA handle that?
I do see why the program you listed above came out with a voltage of 0.789 to 3.05, but, as you say, it is much much too sensitive.