Inline On Dec 25, 2014 1:27 AM, <[email protected]> wrote: > > Hi Ytai, > > Well, will try to go your approach. Most of the program you see there is from open source projects we tried to patch together, but by now we should be able to do a simple program that does as you suggest. > A few questions based on your comments, if I may: > > - you say that our cues are 10 sequencer ticks. We've set it like this as we thought that the smaller it is, the better. I understand now it is not the best approach. > But just to make sure: what is a tick? Here is what I understand now: > 10 ticks = 16 microseconds > the cue should be set to be the period of the input frequency of the ESC. If our ESC has a 1KHz input PWM (according to specs), which means a period of 1ms or 62.5 times of 16 microseconds. > Does this mean the cue should be set to 625 ticks? > Is this right or am I still far off?
As documented on the wiki and the sequencer javadocs, a sequencer tick is 16us. You cannot do fractional ticks. Also, not sure where you got 1KHz from. I'm almost certain that your ESC, when operating in PWM input mode will work with 50-100 Hz, as it is supposed to interface with standard receivers etc. If you want to have faster control you'd have to use its I2C or UART input modes, both possible with the IOIO. But the ultimate decision on what should be your control rate has to do with how fast you actually need to update it in order to match your system dynamics. Unless it is a very small vehicle (which surely cannot carry a phone), 1KHz is an overkill. I'd start with 100Hz and move to higher rates with I2C control if proven insufficient. > > If that is right, than it means the phone will send a new signal to the ESC at each 625 ticks and it should set pulse widths of between 1060 microseconds and 1860 microseconds. > Here is where I get stuck. 1060 microseconds is bigger than 1 millisecond. How can I send pulse widths that are larger than the period? Your understanding is correct. As above, I assert that the expected period is 10ms-20ms. > Also, what do the 2MHz clock and period refer to? > If the number of ticks in the sequencer push already sets the frequency, what are these values for? As per the wiki and Javadocs, different channel types may have a different clock frequency than the sequencer's. In your case you configured it to 2MHz in your channel configuration. Higher rate means greater time resolution, but smaller maximum pulse width, since there's a limit on the maximum number of ticks for the pulse width of 65535. So in general, set the channel clock so that it is as high as possible for your maximum pulse width of about 2ms. > > I am not even sure that this is the place where to ask these questions as they are probably more related to our very basic knowledge on frequency and devices than IOIO. Please let me know if you think we should check out other forums. > All your questions so far have been quite IOIO specific so this is an appropriate place to ask them. > Believe it or not, we got to the magic number of 6111 by doing some math, but later realized that our math was totally wrong however I was baffled that it worked. > > We did go through the motor control page wiki, more than a few times. Probably not having an engineering background doesn't help at all but we went through a lot of material to try to get to the bottom of it and we still don't understand a few things, or better said, the documentation makes total sense to us, but we still find it difficult to convert it to code. Let me know if there's anything I should change on the wiki to make it easier to understand. Most of your questions are answered there, but maybe not clearly enough. > > On Thursday, December 25, 2014 12:52:46 AM UTC+2, Ytai wrote: >> >> First and most important, I think the way you're approaching debugging is inefficient. You're using a long program where a lot of things can go wrong to bring up some very low level functionality. A more effective approach would be to write a very simple program to exercise one ESC and make sure you got that one right. Only then move on to for motors with dumb logic and only then to your actual business logic. >> Concretely, a few things I've noticed: >> - Your cues are super short: 10 sequencer ticks or 16 microseconds as per your push method call. This makes no sense: why would you run your loop at 60kHz? Your ESC probably can't handle more than 100Hz or so anyway, so you're sending updates about 600 times faster than required and in practice probably saturating the Android CPU or the IOIO MCU or the USB link. >> - This magic 6111 number makes no sense. Unless you have a good reason to have chosen it, I propose that you pick your constants according to specs as opposed to trial and error. The latter is a sure recipe for unreliable results and frustration. >> - The code that calculates the PWM bandwidth seems to have some inconsistency between what the comment says and what the code does. A simple test program as suggested would convince you that the problem is not in the low level ESC support code. >> >> BTW, have you seen the wiki page about motor control. It should make the operation of the sequencer clear if it isn't already. >> >> Let me know if you need any more help. >> >> On Dec 24, 2014 1:31 AM, <[email protected]> wrote: >>> >>> Thank you Ytai, >>> >>> The BaseIOIOLooper starts at line 164: https://github.com/cllaudiu/vespi/blob/master/vespidrone/src/ioio/rd/vespidrone/QuadcopterActivity.java >>> The loop is at line 230. >>> >>> The pulsewidth is set starting at line 243 like this: >>> dcMotorNECue_.pulseWidth = mainController.getNEMotorsPowers(); >>> >>> The values returned by mainController.getNEMotorsPowers(); are set starting with line 260 in this file: https://github.com/cllaudiu/vespi/blob/master/vespidrone/src/ioio/rd/vespidrone/MainController.java >>> >>> I've also pasted the code here in case it is more convenient: >>> >>> class Looper extends BaseIOIOLooper { >>> /** The on-board LED. */ >>> >>> private Sequencer.ChannelCuePwmSpeed dcMotorNECue_ = new ChannelCuePwmSpeed(); >>> private Sequencer.ChannelCuePwmSpeed dcMotorNWCue_ = new ChannelCuePwmSpeed(); >>> private Sequencer.ChannelCuePwmSpeed dcMotorSECue_ = new ChannelCuePwmSpeed(); >>> private Sequencer.ChannelCuePwmSpeed dcMotorSWCue_ = new ChannelCuePwmSpeed(); >>> >>> private Sequencer.ChannelCue[] cue_ = new Sequencer.ChannelCue[] { dcMotorNECue_,dcMotorNWCue_,dcMotorSECue_,dcMotorSWCue_ }; >>> private Sequencer sequencer_; >>> >>> /** >>> * Called every time a connection with IOIO has been established. >>> * Typically used to open pins. >>> * >>> * @throws ConnectionLostException >>> * When IOIO connection is lost. >>> * @throws InterruptedException >>> * >>> * @see ioio.lib.util.IOIOLooper#setup() >>> */ >>> @Override >>> protected void setup() throws ConnectionLostException, InterruptedException { >>> showVersions(ioio_, "IOIO connected!"); >>> enableUi(true); >>> //led_ = ioio_.openDigitalOutput(0, true); >>> final ChannelConfigPwmSpeed dcMotorNEConfig = new Sequencer.ChannelConfigPwmSpeed( >>> Sequencer.Clock.CLK_2M, 6111, 0, new DigitalOutput.Spec(2)); >>> final ChannelConfigPwmSpeed dcMotorNWConfig = new Sequencer.ChannelConfigPwmSpeed( >>> Sequencer.Clock.CLK_2M, 611, 0, new DigitalOutput.Spec(3)); >>> final ChannelConfigPwmSpeed dcMotorSEConfig = new Sequencer.ChannelConfigPwmSpeed( >>> Sequencer.Clock.CLK_2M, 6111, 0, new DigitalOutput.Spec(4)); >>> final ChannelConfigPwmSpeed dcMotorSWConfig = new Sequencer.ChannelConfigPwmSpeed( >>> Sequencer.Clock.CLK_2M, 6111, 0, new DigitalOutput.Spec(5)); >>> >>> final ChannelConfig[] config = new ChannelConfig[] { dcMotorNEConfig,dcMotorNWConfig,dcMotorSEConfig,dcMotorSWConfig }; >>> sequencer_= ioio_.openSequencer(config); >>> sequencer_.waitEventType(Sequencer.Event.Type.STOPPED); >>> while (sequencer_.available() > 0) { >>> push(); >>> } >>> sequencer_.start(); >>> } >>> >>> /** >>> * Called repetitively while the IOIO is connected. >>> * >>> * @throws ConnectionLostException >>> * When IOIO connection is lost. >>> * @throws InterruptedException >>> * When the IOIO thread has been interrupted. >>> * >>> * @see ioio.lib.util.IOIOLooper#loop() >>> */ >>> @Override >>> public void loop() throws ConnectionLostException, InterruptedException { >>> //led_.write(!button_.isChecked()); >>> push(); >>> //servo_.setDutyCycle(0.05f + _varValue * 0.05f); >>> //led_.setDutyCycle(0.05f + _varValue * 0.05f); >>> //led_.setPulseWidth(1500); >>> } >>> private void push() throws ConnectionLostException, InterruptedException { >>> dcMotorNECue_.pulseWidth = mainController.getNEMotorsPowers(); >>> dcMotorNWCue_.pulseWidth = mainController.getNWMotorsPowers(); >>> dcMotorSECue_.pulseWidth = mainController.getSEMotorsPowers(); >>> dcMotorSWCue_.pulseWidth = mainController.getSWMotorsPowers(); >>> sequencer_.push(cue_, 10); >>> } >>> >>> >>> >>> >>> The motor pusleWidth is read from this code: >>> // motorsPowers comes as values between 0 and 255 >>> // needs to be transformed to values from 0 to 1 >>> // Math.round((1060.f + (800 * motorsPowers.nw * 0.39f)) * 2); >>> >>> uno_varValue = Math.round(1060 + (motorsPowers.nw * 8)); >>> due_varValue = Math.round(1060 + (motorsPowers.ne * 8)); >>> tre_varValue = Math.round(1060 + (motorsPowers.sw * 8)); >>> qua_varValue = Math.round(1060 + (motorsPowers.se * 8)); >>> >>> The above code works but as the numbers we've set make no real sense to us we are not sure why it works and if it works at the optimal parameters. >>> Here is a video with it working: https://www.youtube.com/watch?v=qXMKKL9BIT8 >>> >>> Thank you very much for looking into this. We plan to actually write an article after we get to the bottom of it as it will hopefully help others as well. >>> Claudiu >>> >>> >>> >>> On Wednesday, December 24, 2014 8:34:40 AM UTC+2, Ytai wrote: >>>> >>>> The multiplication by 2 is only valid for the 2MHz case, where each tick is half a microsecond or each 2 ticks are one microsecond. >>>> The ESC is likely not arming as result of sending the wrong pulse width. Your example doesn't show how you set the pulse width. Also, you seem to be setting the default pulse width to 0 instead of 1060us, which means that every time you stall the sequencer you'd get 0, which the ESC is likely to interpret as a fault. >>>> If you send me the entire code in question (please reduce it to the minimum that demonstrates your problem) I can probably help you find your actual problems and save a few email round trips. >>>> >>>> On Dec 22, 2014 3:20 AM, <[email protected]> wrote: >>>>> >>>>> One more thing. >>>>> >>>>> If I switch to: >>>>> new Sequencer.ChannelConfigPwmSpeed(Sequencer.Clock.CLK_250K, 750, 0, new DigitalOutput.Spec(2)); >>>>> which would translate to the same input PWM freq as with the 2MHz example, the ESC does not arm. >>>>> >>>>> I feel I am missing something basic but I am not sure what. >>>>> >>>>> Claudiu >>>>> >>>>> On Monday, December 22, 2014 12:54:19 PM UTC+2, [email protected] wrote: >>>>>> >>>>>> Thank you Ytai for jumping in. >>>>>> >>>>>> Just tried the value of 40000. The ESC does not arm. >>>>>> Also tried the value of 2000 (the ESC specs state the Input PWM is 1KHz). Same behavior. >>>>>> >>>>>> When switching back to 6100 (it works with 6200 as well and any value in between) things work again. >>>>>> Does this mean that the ESC input PWM freq is at around 350Hz? >>>>>> Do you have any idea how I could probe this? >>>>>> >>>>>> When you say we feed the pulse width in microseconds instead of ticks, what do you mean? >>>>>> The difference I see from your way of feeding the pulseWidth is that you multiply by 2. Is this how it should be converted from microseconds to ticks? >>>>>> If we multiply by 2 like in your example, the ESC doesn't arm. >>>>>> >>>>>> Thank you, >>>>>> Claudiu >>>>>> >>>>>> On Sunday, December 21, 2014 7:45:15 PM UTC+2, Ytai wrote: >>>>>>> >>>>>>> Is it possible that you're confusing the motor (output) PWM rate with the control (input) PWM? >>>>>>> Hobby ESC are almost universally 50Hz (20ms) input. >>>>>>> You also used the wrong type of PWM channel and fed the pulse width in microseconds instead of ticks. >>>>>>> >>>>>>> So I imagine you should need something like: >>>>>>> >>>>>>> // 40000 ticks @ 2MHz == 20000us == 20ms >>>>>>> // Also, the PWM rate corresponds to SPEED not POSITION >>>>>>> new Sequencer.ChannelConfigPwmSpeed(Sequencer.Clock.CLK_2M, 40000, 0, new DigitalOutput.Spec(2)); >>>>>>> >>>>>>> ... >>>>>>> >>>>>>> // Then: >>>>>>> ChannelCuePwmSpeed cue; >>>>>>> >>>>>>> ... >>>>>>> float power = <value between 0 (stopped) and 1 (full speed)>; >>>>>>> cue.pulseWidth = Math.round((1060.f + (800 * power)) * 2); >>>>>>> >>>>>>> On Sun, Dec 21, 2014 at 4:29 AM, <[email protected]> wrote: >>>>>>>> >>>>>>>> Hello, >>>>>>>> >>>>>>>> I am having troubles understanding how the Sequencer works for controlling a couple of ESCs. >>>>>>>> The ESCs are Afro ESC from HobbyKing. Their manual can be here: http://www.hobbyking.com/hobbyking/store/uploads/745353836X1335174X28.pdf >>>>>>>> According to their specs: For PWM input, motor stop / arm below 1060µs, full power at 1860µs. >>>>>>>> That would be the pulse width for controllig the speed of the motor, right? >>>>>>>> >>>>>>>> The code we have in our Android app to initiate the sequencer: >>>>>>>> final ChannelConfigPwmPosition motorESC = new Sequencer.ChannelConfigPwmPosition( >>>>>>>> Sequencer.Clock.CLK_2M, 6120, 0, new DigitalOutput.Spec(2)); >>>>>>>> >>>>>>>> the cue value is set to 10: sequencer_.push(cue_, 10); >>>>>>>> >>>>>>>> and the value that we send for the pulse width are generated as follows: >>>>>>>> uno_varValue = (int) (1060 + (motorsPowers.nw * 8)); >>>>>>>> >>>>>>>> The motor is running with these values but I just can't understand why. >>>>>>>> Some of the questions we have: >>>>>>>> - why only values around 6100 work for the period. The ESC should have an input freq of 1 Khz (according to this: http://www.hobbyking.com/hobbyking/store/__52338__Afro_ESC_30Amp_Multi_rotor_Motor_Speed_Controller_SimonK_Firmware_US_Warehouse_.html) though the manual says this: The default PWM frequency is 18kHz with 800 distinct steps, but may be adjusted to any frequency. >>>>>>>> - why only 2Mhz clock values worked. I was not able to make it work with other values >>>>>>>> - if the documentation says that 1860µs is the value for full power, why I don't get full power when I send 1860(I can send up to 2500 and there is a clear change in the motor speed) >>>>>>>> >>>>>>>> The whole code can be found here: https://github.com/cllaudiu/vespi/tree/master/vespidrone/src/ioio/rd/vespidrone >>>>>>>> >>>>>>>> We are trying to build a drone based on Android and we have some stability issues at this stage. It flies but we find it hard to control it. Before getting into PID tuning and other elements we want to make sure that the Android - IOIO part works perfectly and that we understand what happens there. Thank you for your time. >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to the Google Groups "ioio-users" group. >>>>>>>> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. >>>>>>>> To post to this group, send email to [email protected]. >>>>>>>> Visit this group at http://groups.google.com/group/ioio-users. >>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google Groups "ioio-users" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. >>>>> To post to this group, send email to [email protected]. >>>>> Visit this group at http://groups.google.com/group/ioio-users. >>>>> For more options, visit https://groups.google.com/d/optout. >>> >>> -- >>> You received this message because you are subscribed to the Google Groups "ioio-users" group. >>> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. >>> To post to this group, send email to [email protected]. >>> Visit this group at http://groups.google.com/group/ioio-users. >>> For more options, visit https://groups.google.com/d/optout. > > -- > You received this message because you are subscribed to the Google Groups "ioio-users" group. > To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/ioio-users. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "ioio-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/ioio-users. For more options, visit https://groups.google.com/d/optout.
