how to change stepper direction through limit switch - limit

I am working on a project and am trying to write code for this project in circuitpython on a esp32 s2 board.
Currectly I don't have the hardware setup ready to function so I can't test codes I've written. So all I have to base my findings on are thought experiments and trying to understand what the code will do (which is a good training at it's own IMHO).
One of the difficulties, and the one for this question, is that I am dealing with getting the stepper motor to change direction when an (optical) limit switch is triggered (so far so good i think), but i will also need to keep it in this "reversed" direction once it no longer triggers that switch.
One way, to do so, seems to make it stop looking at the first limit switch as soon as it is triggered and start looking at the switch at the opposite end instead as well as change the direction. Unfortunately i understand this but have no clue how to set this up in code. When it reaches the trigger it this end it needs to do something else entirely so i am really only dealing with this one switch triggered change of direction during initialisation.
while True:
stepper_motor.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(Interstep_delay)
while switch_top.value is False
stepper_motor.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
Step_count = Step_count + 1
time.sleep(Interstep_delay)
while switch_bottom.value is False
#stop stepper motor
Total_count = Step_count.
This is the code I have for now, but it just doesn't feel correct to me. Mainly because I (think I) make it look at the bottom switch but I don't make it stop looking at the top switch but I have no idea how to change this in a correct manner.
Any thought and suggestions are welcome.
Kind greats
PS: I added my code to clarify what I am doing and willing to do. Please help me with the thought experiment. This question is ofcourse not intended for me to end up with a working code still don't understand.
Since post i changed code to this
# initiasation
leds[0] = (255, 0, 0)
while True:
while switch_top.value:
stepper.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(Interstep_delay)
if switch_bottom.value:
stepper.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
Step_count = Step_count + 1
time.sleep(Interstep_delay)
elif switch_bottom.value is False:
Step_count = Total_steps
leds[0] = (0, 255, 0)
if switch_start is False:
leds[0] = (0, 0, 255)
game_function()
but i am still in doubt if it would actually do what i intend it to do.

Related

Why does EnvGen restart on every loop iteration and how to prevent this behavior?

How can I use EnvGen in a loop in such a way that it won't restart at every iteration of the loop?
What I need it for: piecewise synthesis. I want e.g. 50ms of a xfade between first and second Klang, then a 50ms xfade between second and third Klang, then a 50ms xfade between third and fourth Klang and so on, and I want this concatenation as a whole to be modulated by an envelope.
Unfortunately the EnvGen seems to restart from the beginning on every iteration of the loop that plays the consecutive Klang pairs. I want a poiiiiinnnnnnnnnng, but no matter what I try all I get is popopopopopopopopo.
2019 EDIT:
OK, since nobody would answer the "how to achieve the goal" question, I am now downgrading this question to a mere "why doesn't this particular approach work", changing the title too.
Before I paste some code, a bit of an explanation: this is a very simplified example. While my original desire was to modulate a complicated, piecewise-generated sound with an envelope, this simplified example only "scissors" 100ms segments out of the output of a SinOsc, just to artificially create the "piecewise generation" situation.
What happens in this program is that the EnvGen seems to restart at every loop iteration: the envelope restarts from t=0. I expect to get one 1s long exponentially fading sound, like plucking a string. What I get is a series of 100ms "pings" due to the envelope restarting at the beginning of each loop iteration.
How do I prevent this from happening?
Here's the code:
//Exponential decay over 1 second
var envelope = {EnvGen.kr(Env.new([1,0.001],[1],curve: 'exp'), timeScale: 1, doneAction: 2)};
var myTask = Task({
//A simple tone
var oscillator = {SinOsc.ar(880,0,1);};
var scissor;
//Prepare a scissor that will cut 100ms of the oscillator signal
scissor = {EnvGen.kr(Env.new([1,0],[1],'hold'),timeScale: 0.1)};
10.do({
var scissored,modulated;
//Cut the signal with the scisor
scissored = oscillator*scissor;
//Try modulating with the envelope. The goal is to get a single 1s exponentially decaying ping.
modulated = {scissored*envelope};
//NASTY SURPRISE: envelope seems to restart here every iteration!!!
//How do I prevent this and allow the envelope to live its whole
//one-second life while the loop and the Task dance around it in 100ms steps?
modulated.play;
0.1.wait;
});
});
myTask.play;
(This issue, with which I initially struggled for MONTHS without success, actually caused me to shelve my efforts at learning SuperCollider for TWO YEARS, and now I'm picking up where I left off.)
You way of working here is kind of unusual.
With SuperCollider, the paradigm shift you're looking for is to create SynthDefs as discrete entities:
s.waitForBoot ({
b = Bus.new('control');
SynthDef(\scissors, {arg bus;
var env;
env = EnvGen.kr(Env.linen);
//EnvGen.kr(Env.new([1,0.001],[1],curve: 'exp'), timeScale: 1, doneAction: 2);
Out.kr(bus, env);
}).add;
SynthDef(\oscillator, {arg bus, out=0, freq=440, amp = 0.1;
var oscillator, scissored;
oscillator = SinOsc.ar(freq,0,1);
scissored = oscillator * In.kr(bus) * amp;
Out.ar(out, scissored);
}).add;
s.sync;
Task({
Synth(\scissors, [\bus, b]);
s.sync;
10.do({|i|
Synth(\oscillator, [\bus, b, \freq, 100 * (i+1)]);
0.1.wait;
});
}).play
});
I've changed for a longer envelope and a change in pitch, so you can hear all the oscillators start.
What I've done is I've defined two SynthDefs and a bus.
The first SynthDef has an envelope, which I've lengthened for purposes of audibility. It writes the value of that envelope out to a bus. This way, every other SynthDef that wants to use that shared envelope can get it by reading the bus.
The second SynthDef has an a SinOsc. We multiply the output of that by the bus input. This uses the shared envelope to change the amplitude.
This "works", but if you run it a second time, you'll get another nasty surprise! The oscillator SynthDefs haven't ended and you'll hear them again. To solve this, you'll need to give them their own envelopes or something else with a doneAction. Otherwise, they'll live forever.Putting envelopes on each individual oscillator synth is also a good way to shape the onset of each one.
The other new thing you might notice in this example is the s.sync; lines. A major feature of SuperCollider is that the audio server and the language are separate processes. That line makes sure the server has caught up, so we don't try to use server-side resources before they're ready. This client/server split is also why it's best to define synthdefs before using them.
I hope that the long wait for an answer has not turned you off permanently. You may find it helpful to look at some tutorials and get started that way.

How to pyplot pause() for zero time?

I'm plotting an animation of circles. It looks and works great as long as speed is set to a positive number. However, I want to set speed to 0.0. When I do that, something changes and it no longer animates. Instead, I have to click the 'x' on the window after each frame. I tried using combinations of plt.draw() and plt.show() to get the same effect as plt.pause(), but the frames don't show up. How do I replicate the functionality of plt.pause() precisely either without the timer involved or with it set to 0.0?
speed = 0.0001
plt.ion()
for i in range(timesteps):
fig, ax = plt.subplots()
for j in range(num):
circle = plt.Circle(a[j], b[j]), r[j], color='b')
fig.gca().add_artist(circle)
plt.pause(speed)
#plt.draw()
#plt.show()
plt.clf()
plt.close()
I've copied the code of pyplot.pause() here:
def pause(interval):
"""
Pause for *interval* seconds.
If there is an active figure it will be updated and displayed,
and the GUI event loop will run during the pause.
If there is no active figure, or if a non-interactive backend
is in use, this executes time.sleep(interval).
This can be used for crude animation. For more complex
animation, see :mod:`matplotlib.animation`.
This function is experimental; its behavior may be changed
or extended in a future release.
"""
backend = rcParams['backend']
if backend in _interactive_bk:
figManager = _pylab_helpers.Gcf.get_active()
if figManager is not None:
canvas = figManager.canvas
canvas.draw()
show(block=False)
canvas.start_event_loop(interval)
return
# No on-screen figure is active, so sleep() is all we need.
import time
time.sleep(interval)
As you can see, it calls start_event_loop, which starts a separate crude event loop for interval seconds. What happens if interval == 0 seems backend-dependend. For instance, for the WX backend a value of 0 means that this loop is blocking and never ends (I had to look in the code here, it doesn't show up in the documentation. See line 773).
In short, 0 is a special case. Can't you set it to a small value, e.g. 0.1 seconds?
The pause docstring above says that it can only be used for crude anmiations, you may have to resort to the animation module if you want something more sophisticated.

std::copy runtime_error when working with uint16_t's

I'm looking for input as to why this breaks. See the addendum for contextual information, but I don't really think it is relevant.
I have an std::vector<uint16_t> depth_buffer that is initialized to have 640*480 elements. This means that the total space it takes up is 640*480*sizeof(uint16_t) = 614400.
The code that breaks:
void Kinect360::DepthCallback(void* _depth, uint32_t timestamp) {
lock_guard<mutex> depth_data_lock(depth_mutex);
uint16_t* depth = static_cast<uint16_t*>(_depth);
std::copy(depth, depth + depthBufferSize(), depth_buffer.begin());/// the error
new_depth_frame = true;
}
where depthBufferSize() will return 614400 (I've verified this multiple times).
My understanding of std::copy(first, amount, out) is that first specifies the memory address to start copying from, amount is how far in bytes to copy until, and out is the memory address to start copying to.
Of course, it can be done manually with something like
#pragma unroll
for(auto i = 0; i < 640*480; ++i) depth_buffer[i] = depth[i];
instead of the call to std::copy, but I'm really confused as to why std::copy fails here. Any thoughts???
Addendum: the context is that I am writing a derived class that inherits from FreenectDevice to work with a Kinect 360. Officially the error is a Bus Error, but I'm almost certain this is because libfreenect interprets an error in the DepthCallback as a Bus Error. Stepping through with lldb, it's a standard runtime_error being thrown from std::copy. If I manually enter depth + 614400 it will crash, though if I have depth + (640*480) it will chug along. At this stage I am not doing something meaningful with the depth data (rendering the raw depth appropriately with OpenGL is a separate issue xD), so it is hard to tell if everything got copied, or just a portion. That said, I'm almost positive it doesn't grab it all.
Contrasted with the corresponding VideoCallback and the call inside of copy(video, video + videoBufferSize(), video_buffer.begin()), I don't see why the above would crash. If my understanding of std::copy were wrong, this should crash too since videoBufferSize() is going to return 640*480*3*sizeof(uint8_t) = 640*480*3 = 921600. The *3 is from the fact that we have 3 uint8_t's per pixel, RGB (no A). The VideoCallback works swimmingly, as verified with OpenGL (and the fact that it's essentially identical to the samples provided with libfreenect...). FYI none of the samples I have found actually work with the raw depth data directly, all of them colorize the depth and use an std::vector<uint8_t> with RGB channels, which does not suit my needs for this project.
I'm happy to just ignore it and move on in some senses because I can get it to work, but I'm really quite perplexed as to why this breaks. Thanks for any thoughts!
The way std::copy works is that you provide start and end points of your input sequence and the location to begin copying to. The end point that you're providing is off the end of your sequence, because your depthBufferSize function is giving an offset in bytes, rather than the number of elements in your sequence.
If you remove the multiply by sizeof(uint16_t), it will work. At that point, you might also consider calling std::copy_n instead, which takes the number of elements to copy.
Edit: I just realised that I didn't answer the question directly.
Based on my understanding of std::copy, it shouldn't be throwing exceptions with the input you're giving it. The only thing in that code that could throw a runtime_error is the locking of the mutex.
Considering you have undefined behaviour as a result of running off of the end of your buffer, I'm tempted to say that has something to do with it.

How do I create a speed boost in CS6 AS2?

I'm using Flash CS6 with AS2.
I'm in a Game Design class here in High School and we have learned some basic coding. I am currently trying to add a "speed boost" feature when you press the shift button. You're supposed to be able to press it and that would give you a 5 second speed boost. After those 5 seconds, you'd revert back to normal speed. These are the variables I have made:
speed = 6;
boost = 16;
boost_timer = 0;
I've set my speed to 6, and I called 16 (the ASCII code for the Shift Key) "boost". I've also added in a timer for the boos to count to the 5 seconds when I call for it in the main code. Here that part of the code:
if(Key.isDown(boost))
{
speed = 0;
boost_timer++;
speed = 12
}
-
if(boost_timer >= 5)
{
boost_timer = 0;
speed = 6;
}
Now, what I'm trying to do here is make it so that when I press "boost", it will set my "boost_timer" to 0 (which would only matter if and when it's not already at 0). Then, it will start increasing my "boost_timer" and set my "speed" to double the original speed.
In the second piece of code, I make it so that once it reaches 5, it should set the timer back to 0. However, because "boost_timer++" had already been set, even with it getting set back to 0, it would still be increasing. But, even when it gets to 5, it will simply restart the timer and continue resetting the speed to 6. The next time I press the "boost" button, it should set the "boost_timer" back to 0 and re-do the whole thing.
I am planning on adding some sort of power up function for later that will restrict the amount of times you can use the boost, but for now, I would first like to make sure that my game is actually capable of using the boost multiple times.
The actual problem I'm having with the coding I have so far is that whenever I now press the "boost" button, it does, in fact, increase the speed. However, it stays at the boosted speed and never goes back on its own. And for some reason, whenever I press the "boost" button again while already boosted, it reverts back to original speed. It's as if the "boost" button is working as an activate and deactivate button for the boost, but I have no idea why and what part of my code is causing this.
Thank you very much for any help you can give!
Found an answer for you from newgrounds:
If you just want to test if the key isnt pressed at the time, just use:
if(Key.isDown(Key.UP) == false)
or
if(!Key.isDown(Key.UP))
however, if you want to test for the exact point the key is lifted only, you have to use a latch sysetm:
if(Key.isDown(Key.UP)){
latch = true;
}
if(!Key.isDown(Key.UP) && latch){
latch = false;
// put your actions here
}
you can see that it will only be that !Key.isDown(Key.UP) && latch once after the key is pressed, so it will perform the actions,then
will wait until the key is pressed then released again to do the
actions again.
And you shall probably run some function at the point where key is lifted up, to reduce speed and store speed boost leftover values.
also this latch variable shall be set to false on every frame at the point where no more functions precedes, so after event program enters next frame with its value being false
Umh! There is event listener for this already made: adobeMX

Stuck with basic programming of STM32L-Discovery

I've got a STM32L-Discovery Board, which has got a STM32L152R8 microprocessor. I'm quite stuck trying to make basic things work.
I've looked the examples given by ST (the current consumption touch sensor and the temperature sensor), and I think they aren't user-friendly, with so many libraries, sub-processes and interrupts, that make the code really difficult to understand.
I've tried to turn on the blue LED (GPIO PB6), but I can't manage to do that.
My code compiles correctly but does nothing to the board. This is the code of "main.c".
RCC->AHBRSTR = 0x00000002;
RCC->AHBRSTR = 0x00000000;
RCC->AHBENR = 0x00000002;
GPIOB->MODER = 0x00001000;
GPIOB->OTYPER = 0x00000040;
GPIOB->OSPEEDR = 0x00001000;
GPIOB->PUPDR = 0x00000000;
GPIOB->ODR = 0x00000040;
while(1) {}
Am I missing something? Could I find really basic examples somewhere?
Thanks in advance!
The standard peripheral library that ST supplies on their website is a good starting point. It has examples on programming a GPIO. Note that their code is absolutely horrible, but at least it works and is something to start with.
What compiler/debugger are you using? If you are using IAR, then you can view the GPIO registers while stepping thru the code. Please post the values of the GPIO registers to your question and maybe we can help.
RCC->AHBENR = 0x00000002;
Change to "RCC->AHBENR |= 0x00000002;"
This will ensure you enable GPIOB without disabling everything else. The existing code will disabled important things like the flash memory controller and all the other GPIOs.
GPIOB->MODER = 0x00001000;
// This will set pin 6 as output, and all other pins as input. Was this your intent?
Change to "GPIOB->MODER = (GPIOB->MODER & 0xFFFFDFFF ) | 0x00001000;"
This will set pin 6 as an output without changing the configuration of any other pins.
GPIOB->OTYPER = 0x00000040;
// This will set the output type as open drain, meaning you can only pull the line down.
Change to "GPIOB->OTYPER |= 0x00000040;"
Set output as push-pull instead of open drain. You later code attempts to set this line high which will not work as an open drain output will pull to ground or allow the line to float. A push-pull output will allow you to set the line high or low.

Resources