SNL-WaterPower / siweed

Sandia Interactive Wave Energy Education Display (SIWEED)
5 stars 2 forks source link

wave maker stepper speed range #26

Closed ryancoe closed 3 years ago

ryancoe commented 4 years ago

The methods/library we're using to control the stepper motor for the wave maker allows fast motion, but cannot work below a certain limit (2.6 mm/s with our current gearing). This can create jittery behavior, especially in jog mode.

@nickross4444 - Rewrite this if I've misunderstood the problem or left things out

ryancoe commented 4 years ago

@DeepFriedDerp thought this link might be helpful: http://sphinx.mythic-beasts.com/~markt/ATmega-timers.html

DeepFriedDerp commented 4 years ago

@ryancoe thanks for the reference @nickross4444 I couldn't figure out from the diagram (and honestly can't recall from last week) if you are using the MEGA or the Due for driving the stepper motor. Could you or @ryancoe or @delaneyheileman advise on that?

The reason I ask is that there is a lot of readily available library source code and examples for AVR timer/counters, not so much for the SAM3x8e (Due), and the ARM source code (located in that hidden labyrinth that is AppData\Local\Arduino15) contains a mostly empty header file (tone.h) and a disabled copy of the AVR-specific tone.cpp source file. I did fine a list of reference macros related to the SAM3x Timer/counter settings that may be useful if we do end up having to try to reconfigure clock dividers and whatnot.

nickross4444 commented 4 years ago

@DeepFriedDerp The stepper is driven off of the Mega

ryancoe commented 4 years ago

@nickross4444 - Please use this spreadsheet to figure out what we need. Note that I currently have the wave amplitude set of 5 cm and wave frequency of ~4 Hz -- I think these are reasonable, but they are not must-have requirements. Also note that the lead screw pitch and belt gear ratio should be updated; please note those numbers in this Issue thread as well. miniWaveTank.xlsx

AccelStepper: f < 4000 Hz Tone: 31 < f < 65000 Hz

One idea would be to use something like this: https://www.sparkfun.com/products/11420 (would also need a transistor or level-shifter like those used for the encoder #14).

nickross4444 commented 4 years ago

@ryancoe It looks like we can solder over a jumper on that board to enable 5v operation. Looks good to me.

DeepFriedDerp commented 4 years ago

As an alternative path, I have managed to get one of the Timer3 channels to output a square wave the same way as the tone library, but with a range of 1Hz to 31.25kHz, with a resolution of about 1Hz.

As long as we have a free Timer Compare channel on either Timer3, Timer4, or Timer5, where me messing around with the clock prescalers won't break anything else that you are using, then I should be able to get this code up and running in time to serve as a backup to the signal generator shield.

ryancoe commented 4 years ago

From my previous spreadsheet (which should be updated with latest gearings before drawing conclusions), we needed f < 29 kHz, so this Timer3 approach may be viable.

nickross4444 commented 4 years ago

With our new gear ratios(though I suspect the pitch might be incorrect) I came up with about 15kHz as a max frequency. Timer 4 and 5 are used by our interrupts on the mega, but timer 3 should be completely free. With all that in mind, @DeepFriedDerp 's code should be more than sufficient, assuming it is able to run with all the other processes. I would think it'd be fine, since tone() hasn't interfered with anything.

ryancoe commented 4 years ago

To be clear, you're proposing using the Timer3 channel and some code that @DeepFriedDerp has written to create the signal through this?

nickross4444 commented 4 years ago

@ryancoe That or using the signal generator, either should work fine.

ryancoe commented 4 years ago

Ok, I'm ambivalent (because I don't really have the expertise to judge these options). I'm happy with whichever path you prefer.

DeepFriedDerp commented 4 years ago

So I've drafted up and tested the code, and its absolute upper limit is about 15.6kHz. I think the limit here may be due to me loading up the mega with several interrupt functions in order to test the code, which may also be a problem with the MEGA on the SIWEED, unless the Timer4 and Timer5 functions are not happened at a very high frequency. @nickross4444 may be able to comment on the current state of the interrupts.

I've also checked the execution time of some of the setup functions necessary to switch tone frequencies and durations. It looks like the slowest function executes in 60 microseconds, with maybe a few additional clock cycles for all of the bit registers to write and sync.

Since this function, as set up on my MEGA, lacks a 1-to-1 relationship between the expected frequency output and the measured output, given a particular frequency setting, it will probably require some calibration. Given this and the fact that the current maximum frequency is very close to the maximum required frequency for adequate operation, it may be a good idea to purchase the dedicated signal generator breakout, just in case this code does not live up to hype during testing on the actual system. @ryancoe what are your thoughts on this?

Once I document the code, I'll post it to a feature branch and generate a pull request so that the merge operation is contingent on successful unit testing. This code is not in a library format like before, because the timer-compare interrupt vector macros absolutely do not play well outside of a .ino sketch for some reason. I know that tone.cpp got it to work, but I do not have those particular magical powers that it's author obviously has. So in this case, it will require a series of global variables near the top of the main sketch, and some functions down at the bottom of the main sketch. I would have hoped to have avoided this messy implementation...but it works.

Let me know if you have any questions or comments.

nickross4444 commented 4 years ago

The interrupts in their current state do take a decent chunk of processing time, so if we were to use this a dedicated Arduino would probably be the way to go(with this solution). If we're going to use another board anyways, it makes the most sense just to go with the dedicated hardware.

DeepFriedDerp commented 4 years ago

In that case, I tend to agree that the best solution would be a dedicated IC breakout for signal generation. Looking over the datasheet for the waveform generator, it has 28-bit frequency resolution, which works out to ~0.01Hz of resolution up to 3MHz

@ryancoe, should I take an action to purchase a few of these? They are available on Digikey, so we can purchase them with a JIT order. Digikey Link to BOB-11420

ryancoe commented 4 years ago

@DeepFriedDerp - Yes, please get ~5 of these boards and anything else you need for this arrangement.

DeepFriedDerp commented 4 years ago

5x BOB-11420's and associated headers have been purchased. I'll update when they arrive on-site.

SeanPluemer commented 4 years ago

Good news, I believe that The bob-11420's will work. See below for pics, but I was able to generate easily 4hz-20khz. (and higher, but I believe it was said this was the range needed). Below 10hz the waveform looks a bit weird, but I believe that's because of my lack of oscilloscope skills? What I need to do now is to see if I can integrate this into the wave generator code and get it to work from there. image image image

nickross4444 commented 4 years ago

@SeanPluemer very nice. I think that's probably slop in the signal generator, but it should work just fine for stepping.

SeanPluemer commented 4 years ago

Update for this issue: We tried running the servo from the signal generator, everything worked great in the higher Hz. But below 20Hz the servo was still acting jittery. We believe this is because the motor controller appears to be picky about the wave being sent in. As mentioned before, that at low Hz the signal generator does output was not a perfect square wave.

To get around this, Nick pulled a genius move and simply added a MOSFET, triggered by the signal generator. With this, the servo appears to be working perfectly now. All that is left is the software implementation.

image