[SOLVED] FEZ Mini with Existing Car motor

Question about Sensors. Which sensor is a good sensor to use for my project?

  • Ultrasonic Sensor (e.g. Parallax PING)))
  • IR distance sensor (e.g. Sharp GP2Y0A21)

Please advice.

Greetz,
Colin

Ps. Need to check if the car is driving know, the battery was empty in the afternoon :S

Car is running know. I only need to tweak some timings.
When i change the speed of forward or reverse, sometimes the ESC isn’t responding on reverse anymore.
Is use the following timings:


uint timing_forward = 100 * 15;
uint timing_reverse = 100 * 10;
uint timing_stop    = 100 * 5;

timings[0] = timing_direction; // timing_forward or timing_reverse or timing_stop
timings[1] = (100 - speed) * 1000;

oc.Set(true, timings, 0, 2, true);

So when i change the [speed], reverse isn’t responding.

Need to investigate more… To be continued.

  1. Where you able to find a datasheet or wave diagram or more details (i.e. forum post) on your ESC cmds?
    It smells like it could be similar issue with this
    http://www.tinyclr.com/forum/1/2830/
    If you interrupt the current signal for a new signal, depending on time, it can mean something else to the servo/controller. May also be a good excuse to invest in a logic prob :slight_smile: http://www.sparkfun.com/products/8938

2)Not sure on the dist sensor thing. When I have a question like that, I get both :-). Use the other one for something else, like reverse or other project.

Forward to reverse often requires you to ramp between the two - for instance, setting full forward to full reverse may make the ESC assume the signal is not good. Try setting to 0 then pause (insert appropriate time here) and then move to reverse.

Also, you should chek out Chris’s RWAR project code, I’m sure he has this situation considered and documented in his code!

Got an answer from Hitec about the ESC.

“Thank you for choosing Hitec products. The SP-560 uses a PWM signal from 900uS to 2100uS with 1500uS as neutral.”

How can i translate uS to signal in CS:

Thanks for answering.

Based on this info, not sure where your Direction stuff is coming from?


// huh? What is timing_direction?
timings[0] = timing_direction; // timing_forward or timing_reverse or timing_stop
timings[1] = (100 - speed) * 1000;
oc.Set(true, timings, 0, 2, true);

It would seem to be more like:

uint fullReverse = 900;
uint fullForward = 2100;
uint neutral = 1500;

timings[0] = fullForward;
timings[1] = 20000; // at least a 20ms low time. Could also use a subtraction to get 20ms total high/low, but may not be needed.

oc.Set(true, timings, 0, 2, true);

Also remember, you can hook the signal pins direct to hw PWM pins to do this in hw instead of OC. You could also ask them if the period is indeed 20ms as we are assuming here. AFAIC, the period is not much important as high time is the critical factor as long as your at least 20ms period. But never know from vendor to vendor if something is critical. Also, if you concider sw OC variables such as scheduling, random GC, etc - you could have some spuratic ESC behavior.

Wow, William, thanks! Will check this out tomorrow first thing!

Will let you know.

Hmz, didn’t worked out as i expected.

Have found something else about the ESC:

Can someone convert this to readable (C#) code (with OC)?

Everytime i try something, it will do almost nothing (stutter a bit) or fullpower.

[edit] dup

The description does not really change anything in terms of driving the pwm afaict. I does, however conflict with what they told you in other email a bit. They said 900-1500 range. This says 1000 - 2000 range.
The one thing I might try is reduce 20000 to 15000 in the code. It looks like 20ms is upper bound so I would try something more in the middle of their required range. Does that change anything?
If not, I would try a real pwm pin before doing much more diag on current method. If that not work either can beg or borrow a logic analyser like a Saleae Logic to inspect how it works when controlled from RC hookup?

Also, can we see your new code as it is today?

Don’t know if it helps, but some RC controlleres need full throtle and then full stop on startup. This is how they know full range. Maybe you need to do that in code?

I’ve finished a similar project, a boat.

I tried a couple of GPSes, but the one I was most happy with was the LS20031.
Regarding motor controllers, spare yourself the trouble and buy a pololu one - they’re really easy to interface with :). (One pwm pin which goes duty 0 - 100% (CMOS), and two control digital CMOS inputs for controlling direction/braking)

Xarren, which pololu do you recommend? (link?)
And also reverse? or only forward?

Pololu - Dual VNH3SP30 Motor Driver Carrier MD03A This one here. Just check the rating of your motor to make sure it can handle it. It’s got forward, reverse and brake, drives two motors.

If you want to, I can send you the source for my project, it should work for you out of the box. Just plug a GPS, IMU (Or use gps data) and the motor controller.

I like the pololu stuff. But for $50 plus s/h, I think he should be able to get his existing stuff running. Did you try the 15000 in code? No effect? Any work on getting a logic prob from a friend? If all else fails, for the cost of SH back and forth, I could take a look at it.

Not working with 15.000 or 20.000, always fullthrottle.

I also got a code with PWM_UsingOC, but same results.

This is my code in OC only:

//
// Import Namespaces
//
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
//
// FEZ NETMF Namespace
//
namespace GHIElectronics.NETMF.FEZ
{
    //
    // FEZ_Components Partial Class
    //
    public static partial class FEZ_Components
    {
        //
        // ServoController Class
        //
        public class SpeedController : IDisposable
        {
            //
            // Declare Output Compare Object
            //
            OutputCompare oc;
            //
            // Declare Timings Array
            //
            uint[] timings = new uint[2];
            //
            // Declare Signal Timings for Electronic Stability Control (ESC)
            //
            uint frequency = 20000;
            uint neutral = 1500;
            int fullForward = 2100;
            int fullReverse = 900;
            //
            // Set Direction State Enumeration
            //
            public enum DirectionState : byte
            {
                Forward = 0,
                Reverse = 1
            }
            //
            // Dispose Function
            //
            public void Dispose()
            {
                oc.Dispose();
            }
            //
            // SpeedController
            //
            public SpeedController(FEZ_Pin.Digital pin)
            {
                //
                // Create Output Compare Object
                //
                oc = new OutputCompare((Cpu.Pin)pin, true, 2);
            }
            //
            // Drive Forward
            //
            public void DriveForward(int speed)
            {
                //
                // Set New Speed
                //
                uint newSpeed = (uint)ScaleRange(speed, -100, 100, fullReverse, fullForward);
                //
                // Set Signals
                //
                timings[0] = newSpeed;
                timings[1] = frequency;
                //
                // Send Signal To OutputCompare
                //
                oc.Set(true, timings, 0, 2, true);
            }
            //
            // Set Stop Signal for ESC
            //
            public void Stop()
            {
                //
                // Set Signals
                //
                timings[0] = neutral;
                timings[1] = frequency;
                //
                // Send Signal To OutputCompare
                //
                oc.Set(true, timings, 0, 2, true);
            }
            //
            // Scale a number within a source range to a new range and return new scaled value.
            //
            private static int ScaleRange(int oldValue, int oldMin, int oldMax, int newMin, int newMax)
            {
                return ((oldValue - oldMin) * (newMax - newMin) / (oldMax - oldMin)) + newMin;
            }
        }
    }
}

Have you got any other signal generator laying about?

An astable with a variable resistor?

Would be much simpler to see if you can get any different response from it.

I think I may have spotted the issue. OC is started on full blast in ctor.
Try this and let me know.


public class SpeedController : IDisposable
{
    readonly OutputCompare oc;
    readonly uint[] timings = new uint[2];
            
    // Declare timings for Electronic Stability Control (ESC)
    const int PERIOD = 15000; //Us
    const int NEUTRAL = 1500; //1500us = 1.5ms
    const int FULLFORWARD = 2000;
    const int FULLREVERSE = 1000;

    public SpeedController(FEZ_Pin.Digital pin)
    {
        // Start OC low (not full blast).
        oc = new OutputCompare((Cpu.Pin)pin, false, 2);
            
        // "Arm" the ESC. Guessing this might be required for ESC, but should not hurt if not.
        Stop();
        Thread.Sleep(500);
    }

    public void Dispose()
    {
        Stop();
        oc.Dispose();
    }

    public void Drive(int speed)
    {
        if (speed < -100 || speed > 100) throw new ArgumentOutOfRangeException("speed");
        uint newSpeed = (uint)ScaleRange(speed, -100, 100, FULLREVERSE, FULLFORWARD);
        SetSpeed(newSpeed);
    }

    public void Stop()
    {
        SetSpeed(NEUTRAL);
    }

    private void SetSpeed(uint speedUs)
    {
        timings[0] = speedUs;
        timings[1] = PERIOD;
        Debug.Print("High: " + timings[0] + " Low: " + timings[1]);
        oc.Set(true, timings, 0, 2, true);
    }

    private static int ScaleRange(int oldValue, int oldMin, int oldMax, int newMin, int newMax)
    {
        return ((oldValue - oldMin) * (newMax - newMin) / (oldMax - oldMin)) + newMin;
    }
}