Just Yacking outload about an algorithm...
TinkersALot
Posts: 535
Okay, So lets say I have "n" 165's as inputs that I want to sample at some frequency.
Next, let's say I have "n" 595's as some outputs that should "follow" the inputs with some "decay";
where the decay is represented by a decreasing duty cycle for the output bit at that "shift position."
Each "output follower" would have its decay related to only its input "bit position".
So, in rough terms, I want to read in 'n' bits. For each bit that is found to be 'on' I want to start an output pulse on the output bit. The output bit would at first have a very long duty cycle. Then for each sample of the input pins, if a bit position (that was previously on was now off), the duty cycle for the signal on its corresponding output pin would be reduced (toward zero).
In rough terms I am trying to describe a "slow fade" of a number of output pins related to a high signal on a a set of input pins.
Does that make sense?
Seems simple enough, but the devil will be in the details. Has anyone ever seen anything like this, or will be discovering this from the scratch point?
Next, let's say I have "n" 595's as some outputs that should "follow" the inputs with some "decay";
where the decay is represented by a decreasing duty cycle for the output bit at that "shift position."
Each "output follower" would have its decay related to only its input "bit position".
So, in rough terms, I want to read in 'n' bits. For each bit that is found to be 'on' I want to start an output pulse on the output bit. The output bit would at first have a very long duty cycle. Then for each sample of the input pins, if a bit position (that was previously on was now off), the duty cycle for the signal on its corresponding output pin would be reduced (toward zero).
In rough terms I am trying to describe a "slow fade" of a number of output pins related to a high signal on a a set of input pins.
Does that make sense?
Let's see if I can "draw some signals" to illustrate the idea in 1 ___----________________---___ in 2 _______---_____________________________---___ ot 1 __-------___-----_____---___-------___-----_____---__________ ot 2 _______-------___-----_____---______________-------___
Seems simple enough, but the devil will be in the details. Has anyone ever seen anything like this, or will be discovering this from the scratch point?
Comments
When I first started playing with some 8x8 RGB LED arrays, I initially tried it Spin. Updating the '595s was so slow the LEDs would flash rather than dim.
The code I posted in the above mentioned thread PWM the LEDs at up to 8-bits of resolution. It may be chore to trim away all the unneeded stuff from the code so you may be better off using code from the OBEX with can drive up to four '595 chips with PWM.
I'd have one section of code continually modifying (dimming) values in a buffer representing the desired brightness of the LED. Another section (cog) would read these values and drive the '595 appropriately.
Edit: After rereading your original post, now I'm not so sure. It kind of looks like you want to stretch the incoming pulses and send them to the outgoing pulses? What's the relationship between the sampling frequency and PWM frequency?
I'm still inclined to think you'd be better off controlling the output from a separate cog based on the values in a buffer. The values in the buffer would be set by a different cog reading the inputs.
Any guess on the value of "n"? There's a definite trade off between the number of '595 being driven and the brightness resolution of the LEDs.
Edit again: Reading the OP again, I think I may have projected my own projects onto what you want to do. Now I'm not sure what you mean by "slow fade". I had assumed you meant you wanted to dim the the output (which I now realize my have nothing to do with LEDs).
In my view, the solution is just implementing a 32 bit register to control each output at the '595.
You can load them all at startup, with a value of your choice, perhaps a 50/50 duty cycle signal, with 16off and 16on bits.
Then you can read each corresponding controlling bit position at the '165 and decide if you must left or right shift its controled register, adding a leading one or trailing zero.
Provided your application can be tolerant to an output scan rate that is 32 times the input scan rate frequency, I am certain you can 'see' at an osciloscope screen, exactly what you meant.
If it's not your intent to do something like this, then your comments can lead us to a better understanding of your actual needs.
Yanomani
edited: Looking again at your original post, I believe I'd missing something. Lets see...
It's your intent doing something like a 'snapshot driven' control or, perhaps, a 'history driven' control?
Or are my thoughts a bunch of misleading ones?
Yanomani
I can imagine that a rising edge that sets a counter to 255. At each time tick after that, the counter decrements until it again reaches zero. A rule for output at each tick is: If the value of the lower nibble is less than value of the upper nibble, then the output is made high, otherwise low. That would be a linear fade.
I may be completely misunderstanding too. Is there a going to be a microcontroller in between these shifters? We need more context and detail. (That's what you get for yacking!)
Do you want to sample for say 1 second, and them output for say 10 seconds (at 1/10 the frequency)?
Not getting the slow fade idea.
I think you are on to it -- and have provided a technique that I can use as a starting point. I was going to drop a prop in the middle of the 165s and the 595s. One cog would be sampling the 165s, and drop a long into a shared buffer, another cog would read that buffer for deltas and would apply the "fader" routine and those results would be dropped into its output buffer, the output cog would shift the result from the "fader cog" to the 595s. Another challenge would be to to determine the sample rates at the 'cog boundaries'. For instance, the "fader" and the "out shifter" would have to run at a higher speed than the input sampler and it would have to be responsive to the input scan so that the device would not miss edge events.
Now why couldn't I say it like that. This is spot on.
If the output pulse frequency is to be constant then any time subtracted from the high time will be added to the low time. Since you were thinking of using '165's and '595's I'm guessing the frequency will be low enough to use PASM or possibly even Spin.
What sort of frequencies and number of channels did you have in mind?
Nice bits of analysis here, kwinn.
To start, I am thinking of 16 inputs (two 165's lashed in "series" ) with an equal amount of outputs (though I could see some value in 32 outputs, with a pulse-train and a inverted-levels pulse train for each input channel (this could be done with 4 595s -- or with 2 595s and an inverter off each output (likely much easier)).
Sample frequency of the input channels would be *very low*. I think I could easily get away with a 10 Hz sample rate, but may sample at 100 Hz (10x oversample). Even with the "shift-in overhead" involved, I think this would be plenty fast for the application I have in mind. And I think this would still be fast enough for me to detect "signal level changes" on the inputs (I don't think I need to necessarily detect edges with this project).
In thinking about how I may decompose this, I think a "shift in" cog would just shift in the bits, and then write a message to the "mixer cog" for processing.
The mixer cog would first try to detect each bit location where the signal has gone high. (the mixer could mask out that bit location from that point until it had seen the same bit position go to a low state (that would clear the masking of that bit).
The "mixer cog" would would initialize the pulse train for each bit position that had had toggled to a high state. It would "launch" a pulse train for that bit position with the first pulse having a width 100 milSecs. The "mixer cog" would also loop over all "active pulse trains" reducing them by 5 milSecs on each successive pulse. The "mixer cog" would manage all the timing for all the bit positions and would then just write the resulting bit mix to an output buffer to be read by an output-cog.
The "output cog" would simply shift out whatever mix of bits it was sent.
Since you need the same number of chips either way I would go with the inverters. It makes the software simpler and faster.
If you have cogs to spare:
Cog 1 (Input) could read the input from the '165's and save it in variable1.
Cog 2 (Mixer) could could read variable1, produce, and store the output bit pattern in variable2.
Cog 3 could read variable2 and output it to the '595's
Since cog 2 would have the most time consuming task and limits the speed of data I/O you can connect the '165's and '595's so they share some signals and have a single cog read the input and write the output simultaneously.
The mixer cog is going to be one very busy little cog so perhaps multiple cogs (say 4) could be made mixer cogs and each one works on 4 of the 16 bits.
BTW, since the pulse width has to be reduced by 5mS on each successive pulse the mixer loop has to be pretty fast to get it all done so PASM may be required. Maybe try spin first and if it is not fast enough switch to pasm.
All three cogs could be synced to the 5ms cycle. For cog 2, the rising edge on a pin could set the corresponding counter to a value of 400. Each subsequent sample period tests the counter and sets the corresponding output bit based on a comparison of counter/20//20 to counter//20 and decrements the whole counter by 1. The cycle of counter//20 takes 100 milliseconds. The proportion of time the output bit is high in each successive 100ms period decreases as the high bits decrease.
if counter[.] // 20 =< counter[.] / 20 // 20 then result<<1 + 1 else result<<1
(The math can be simpler if the cycle count is a power of 2, also it can be condensed with computed intermediate results.)
I think that could work as a pretty tight state machine. I don't know if spin could do it in 5ms for 32 channels, but pasm certainly could.
@Kwinn -- good idea about dividing up the bits across more than one "mixer cog" to divide the load of the pulse train manipulations
Thank you both so much for these inspired ideas
I was thinking along these same lines -- the inputs/trigger signals are completely unrelated to all other of the others. The outputs are not related to another either. Each of their pulse trains is only related to the event that started the train. But looks like I will get to learn alot about timers with this project
Can you elaborate on the relationship between the input trigger and output signal? Since you are only interested in triggering the output with the leading edge of the input I'm guessing the input on channel x always triggers the same output signal on output y. I am very curious as to what the application for this would be. Care to provide a hint?
I am working on an interactive sculpture installation where the observer would trigger one or more inputs and the sculpture would respond in a way that fades over time but will "reinvigorate" with each new trigger. Admittedly a wild eyed notion, but that's what's on the bench.
curious in return: what were some of the guesses that you thought this would have been applied toward?