Have inputs that are square waves
Hi all,
I'm hoping someone can help me with a project that seems to have beaten me after lots of experimentation and debugging. If you can help, I'd be most appreciative. Below is the problem, and I've tried to describe it the best I can. If there's any add'l info that can help you help me, please let me know. Thanks!
I'm working on a senior project and basically stated, I have a square wave generated by the Propeller that's 1kHz, with variable duty cycle. The duty cycle can be as small as 5% or as large as 96%. This signal (0V to 3.3V) is put through a unipolar to bipolar converter (+12V to -12V), then passed through some hardware. The result is that as the circuit changes, the +12V peak is reduced to +9V and +6V (but the -12V reference stays the same). The bipolar square wave is then put through a stack of parallel comparators, and that feeds back into the Propeller. If the square wave is +12V, then all comparators are on. If the square wave is +9V, then the "top" comparator is off but the ones below that are on. If +6V, the top two comparators are off but the rest are on, and etc. Those signals is brought back down to 0V to 3.3V for input to the Propeller.
The challenge is that the comparators are turning on and off with the duty cycle of the square wave so I'm trying to "time" the code correctly to look at the inputs once per cycle. What's odd is that I *think* I've written the code to do what I want, but it's not performing well.
What I've been trying is a POSedge detection...I've fed the square wave output pin into an input pin and then increment PSHA whenever a POSedge has been detected. What I figure is that PSHA will be incremented every time there is a positive edge, so I tell my code that when PSHA equals 1, reset it to zero, then run my logic code. This is in a repeat loop that contains all my code logic (if the square wave is at 12V do this, if 9V do this, etc).
The problem is that my code is doing something that isn't what I *think* I'm asking it to do. A good example is that one of my debugging techniques has been to put a wait command at the end of the repeat loop. I figure if the code runs once and gets to the wait loop, it should wait exactly one second before PSHA sees another positive edge, increments, and then my repeat loop is run where PSHA is reset to 0 and the logic code runs again. This, in actuality, is not what happens. If I ask it to wait one second, it'll actually not respond until about 10 seconds have past. If I ask it to wait 10 seconds, it waits forever. If I ask it to wait for a tenth of a second, it waits for about 1.
The greater problem is that the logic code is not working correctly based on the changing inputs, and I think the instability of the Propeller "looking" at the inputs is the culprit.
Instead of randomly throwing numbers in a wait command to bang it into working, I'd like to figure out why it's not doing what I'm asking, and then go from there. Maybe I'm not using POSedge correctly, maybe I don't understand the timing of the Propeller correctly, I'm not sure.
I have two ideas, not sure if they'll help. First, should I also use a NEGedge command to keep the Propeller waiting to look at the inputs again until the square wave is done for that duty cycle? I haven't tried that yet, but it's an idea. Second, would it be better to rewrite the code so that when there is a positive edge detected the inputs are treated like an array, and then the logic code is run on those values? Then I'm not looking at the inputs in real time, I'm looking at stored values. That's easier said than done, I'm not sure how I would code that in SPIN at the moment but it's an idea.
Sorry this is so long guys, I've tried to be descriptive and accurate so that the problem is clear. If you want to see the code let me know and I'll put it up. Thanks for any help! I've found through this project that what I want the Propeller to do versus what I'm actually programming can be drastically different, so I appreciate any insight from people that have more experience than me!
I'm hoping someone can help me with a project that seems to have beaten me after lots of experimentation and debugging. If you can help, I'd be most appreciative. Below is the problem, and I've tried to describe it the best I can. If there's any add'l info that can help you help me, please let me know. Thanks!
I'm working on a senior project and basically stated, I have a square wave generated by the Propeller that's 1kHz, with variable duty cycle. The duty cycle can be as small as 5% or as large as 96%. This signal (0V to 3.3V) is put through a unipolar to bipolar converter (+12V to -12V), then passed through some hardware. The result is that as the circuit changes, the +12V peak is reduced to +9V and +6V (but the -12V reference stays the same). The bipolar square wave is then put through a stack of parallel comparators, and that feeds back into the Propeller. If the square wave is +12V, then all comparators are on. If the square wave is +9V, then the "top" comparator is off but the ones below that are on. If +6V, the top two comparators are off but the rest are on, and etc. Those signals is brought back down to 0V to 3.3V for input to the Propeller.
The challenge is that the comparators are turning on and off with the duty cycle of the square wave so I'm trying to "time" the code correctly to look at the inputs once per cycle. What's odd is that I *think* I've written the code to do what I want, but it's not performing well.
What I've been trying is a POSedge detection...I've fed the square wave output pin into an input pin and then increment PSHA whenever a POSedge has been detected. What I figure is that PSHA will be incremented every time there is a positive edge, so I tell my code that when PSHA equals 1, reset it to zero, then run my logic code. This is in a repeat loop that contains all my code logic (if the square wave is at 12V do this, if 9V do this, etc).
The problem is that my code is doing something that isn't what I *think* I'm asking it to do. A good example is that one of my debugging techniques has been to put a wait command at the end of the repeat loop. I figure if the code runs once and gets to the wait loop, it should wait exactly one second before PSHA sees another positive edge, increments, and then my repeat loop is run where PSHA is reset to 0 and the logic code runs again. This, in actuality, is not what happens. If I ask it to wait one second, it'll actually not respond until about 10 seconds have past. If I ask it to wait 10 seconds, it waits forever. If I ask it to wait for a tenth of a second, it waits for about 1.
The greater problem is that the logic code is not working correctly based on the changing inputs, and I think the instability of the Propeller "looking" at the inputs is the culprit.
Instead of randomly throwing numbers in a wait command to bang it into working, I'd like to figure out why it's not doing what I'm asking, and then go from there. Maybe I'm not using POSedge correctly, maybe I don't understand the timing of the Propeller correctly, I'm not sure.
I have two ideas, not sure if they'll help. First, should I also use a NEGedge command to keep the Propeller waiting to look at the inputs again until the square wave is done for that duty cycle? I haven't tried that yet, but it's an idea. Second, would it be better to rewrite the code so that when there is a positive edge detected the inputs are treated like an array, and then the logic code is run on those values? Then I'm not looking at the inputs in real time, I'm looking at stored values. That's easier said than done, I'm not sure how I would code that in SPIN at the moment but it's an idea.
Sorry this is so long guys, I've tried to be descriptive and accurate so that the problem is clear. If you want to see the code let me know and I'll put it up. Thanks for any help! I've found through this project that what I want the Propeller to do versus what I'm actually programming can be drastically different, so I appreciate any insight from people that have more experience than me!
Comments
Mathematically, you are correct there are 1000 positive edges in one second. What I meant was, if I waitcnt the code from proceeding for one second, it should be one second before it goes and looks again at the inputs.
And yeah, I'll get the code up and posted so it'll be easier to see what I'm doing. I'll clean it up and remove some old commented out stuff, then put it up. Thanks for the quick response!
Second issue is the software. You can do this in Spin or PASM. At 1khz, spin should be fast enough. What are you trying to measure - the frequency or the duty cycle or both? If you are wanting to measure the duty cycle, how much accuracy do you need? eg if 1khz and you want it to the nearest 1%, that is now the same as measuring a 100khz wave. It can all be done though, as the propeller has the cnt() function which ticks along at megahertz speed. I presume you have an external crystal (5Mhz?). If so, you can detect the edge, then wait till it changes, then wait till it changes again, and with those three counter values you can work out both the frequency and the duty cycle.
Maybe post some code first, and we can work on that.
Here is my code, cleaned up a bit and hopefully understandable.
Specifically, the project is a charger for electric vehicles. The basic functionality is this:
1. if no vehicle is present, the signal output is +12V with ground reference.
2. if a vehicle is plugged in, the square wave starts and the peak is now +9V (dropped by voltage dividers in the vehicle), with -12V reference.
3. if the vehicle wants to charge, the square wave drops further to +6V (again dropped by voltage dividers in the vehicle), with -12V reference.
The vehicle actually takes in 120/240VAC and does all the rectification/filtering itself, so the microcontroller is basically controlling solid state relays that provide the AC voltage.
The frequency of the square wave is 1kHz, but the duty cycle can vary from 5% to 96% and this tells the vehicle how much current it can pull. The most the duty cycle can vary is 2%.
Basically, the square wave signal goes through comparators and based on where the peak voltage of the square wave is (+12 DC, or +9/+6 square wave) the microcontroller knows if a vehicle is present (start square wave), whether or not it wants to charge, and if the vehicle has been disconnected (square wave cog is killed).
Any questions, let me know. Thanks for the help!
posted_to_forums.spin
Well, that's a good question. I'm not actually trying to measure the frequency or duty cycle...what I am trying to do is look at the square wave only when it's positive. With the eight parallel comparators, their outputs will say if the vehicle isn't present (which will be a +12V DC signal), if the vehicle is present (a +9V square wave) or if the vehicle is present and wants to charge (+6V square wave). I believe my problem is that I'm trying to look at the square wave only when it's positive, but in actuality the code is looking when it's negative, possibly during transitions. What I'm trying to do is get the code to look at the square wave only when it's positive. Does that make sense?
if the square wave is at 5%, it could be as low as 3% or as high as 7% and still meet the technical specification.
that is correct.
i don't need to measure the actual duty cycle or frequency as described above, but what you describe (detect edge, wait till it changes, wait till it changes again) is exactly what i want to do, and have been trying to do, but have been unsuccessful at getting solid, stable operation. any help is very much appreciated!
You could try simple manual edge detection possibly in a separate cog as it would block and I'm not sure how much of your main loop needs constant attention. @80MHz this will get you about 180..1160 cycles into the high part of the incoming square wave. I don't know if the monitored square wave has the same duty cycle as the one sent out. Even if that's the case the minimum high cycle seems to be about 7k2 (clkfreq/11000) so plenty of cycles left. That said, SPIN isn't a speed monster so whatever inputs you want to sample, get them immediately after you detect the edge (short of involving PASM).
To be honest I'm still not entirely sure what you want to look at and when but I'm sure we figure this one out.
Yeah, that was a concern for me as well. I was trying "greater than or equal to 1" but it wasn't helping. I tried "equal to 1" as an experiment, and that's where I left off.
I had just read about waitpeq and waitpne like yesterday...definitely looks like it might be promising. I'll work with that a bit, see if it'll help. As far as how much my main loop needs constant attention, I'd say I'd like to run the loop every tenth of a second. That way it seems instantaneous to the user, but it isn't burning up clock cycles unnecessarily.
It does have the same duty cycle, it's actually the exact same signal. See below for more info that may help.
Let me see if I can help explain what I'm doing, I know it can be hard to understand via forum messages. Here are some notes I hope are helpful:
1. The microcontroller produces a square wave, whose duty cycle tells the electric vehicle how much current it can draw. This is put through a bipolar square wave generator (op amp as a differential amplifier) to go to +12V and -12V.
2. This square wave is sent to the vehicle, where internal resistive voltage dividers alter the signal; if the vehicle is present, it's a +9V square wave. If the vehicle wants to charge, an additional voltage divider brings the voltage down to +6V.
3. This square wave is also sent through comparators (this is in electrical parallel with the vehicle's voltage dividers). As the voltages change, the comparators report either a high or low output...this is fed into the microcontroller as 1s and 0s as a parallel line of eight inputs.
4. Because the square wave is going through the comparators, the comparators only have useful outputs whenever the square wave is high...if it's low, every output is low and no information is there.
5. What I need is the microcontroller to basically say "Ok, the square wave is high. Take a look at the comparators, and if the car wants to charge (as indicated by the comparators saying the square wave is at +6V) turn on the relay controlling the 120VAC from the wall. Now wait until the square wave is high again before looking at the comparators again."
6. I think the problem is that my code is looking at the comparators both when the square wave is positive, and also negative.
7. The charging is controlled by time of day (only charge at night) and simulated grid health. What we need to do is only turn on the charging at night, and then throttle the charging. This means real time throttling (changing of square wave duty cycle), turning on the 120VAC, and then turning it off when the car is done charging. The simulated grid health is a signal from a DAQ coming in from Labview for demonstration purposes.
8. I'm not interested in reading the frequency or duty cycle of the wave the microcontroller is creating. I'm trying to get the code to only run when the square wave is positive, so that the microcontroller only looks at the comparators when they have usable outputs.
I've included the schematic of what we're doing and a block diagram. I hope this is coming across as understandable, if not then let me know and I'll try to clear up what's going on.
Exactly. I'm glad that I was able to explain that.
I was worried about this...I was wondering just how long it took to execute all this code, and was worried I was getting to the limits of what SPIN (instead of PASM) could do.
I somewhat understand what you're doing here, but I've been having one heck of a time figuring out whether waitpne and waitpeq are waiting until high or waiting until low. I've read the SPIN manual and it's just not clicking...could you walk me through this code that you suggested? Additionally, could you suggest where to put this code? I'm assuming I would remove POSedge detection and use this instead...would it go all in one spot, above the logic portion of my code?
I also somewhat understand this, but need some clarification. Does the special register bout look at all the I/O pins, and bit 20 is pin 19? Or is it something more complicated than that? I'll read through the SPIN manual looking for info on this special register. If you have suggestions for where to look, I am all ears. I notice you're in Japan, so I'm trying to fight our time difference and ask questions I can look up during my tomorrow (hence my 1am pacific time post). What I mean is, I will do my own independent research but if I perchance get a message from you tomorrow before I start, it may be helpful instead of waiting a day for a response.
Thanks so much for helping me with this, I greatly appreciate it!
Do you mean, can I guarantee that my comparator values are past transition times and are steady high by 180 cycles? I believe I can, but I will fire up the oscilloscope tomorrow and verify that I can guarantee this. If this isnt' what you mean, please let me know what you mean and I'll figure it out. Thanks!
Yes, it would effectively replace the if statement. As you get 1000 transitions per second and you want something like 10Hz updates the blocking nature shouldn't be an issue. You may want to slow down the loop artificially (e.g. with waitcnt).
The prop has 32 I/O pins (0..31). By reading ina you get each pin assigned to a bit in that register. Accessing outb[20] (after assignment) is bit 20 (the 21st one) or for a DIP prop pin 25 (see data sheet). You can access outb[0]..outb[31]. Hope that's not too confusing.
Because the square wave can be switched off you want to guard the edge-detection by something like if wave_active which should cover all code up to but excluding the waitcnt(base += granularity).