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?

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?
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?

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.

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.

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] <javascript:>> 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.ChannelConfigPwm*Speed*(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/74535
>>>>>>> 3836X1335174X28.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/cllau
>>>>>>> diu/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] <javascript:>.
>> To post to this group, send email to [email protected] 
>> <javascript:>.
>> 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.

Reply via email to