Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Netduino Outlaw Derby - in progress


  • Please log in to reply
8 replies to this topic

#1 EddieGarmon

EddieGarmon

    Member

  • Members
  • PipPip
  • 24 posts

Posted 17 February 2015 - 12:18 AM

My outlaw pinewood derby car for this year:

 

Netduino Plus 2 controller, 25 amp ESC, multiple batteries, ducted fan, solder, and code.

 

Video of the build: http://1drv.ms/1EmgKUE

 

This runs on a new framework which includes an implementation of TPL for NETMF. I intend to release the framework on GitHub soon.

 

//Eddie



#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 17 February 2015 - 12:30 AM

Great project and great video, Eddie. Please share code--and more of your experience!

Zoom, zoom, zoom.

Chris

#3 David Weaver

David Weaver

    Advanced Member

  • Members
  • PipPipPip
  • 50 posts
  • LocationBloomington IL

Posted 19 February 2015 - 07:12 PM

Can it serve a beer it a lot faster than the old beerbot?



#4 EddieGarmon

EddieGarmon

    Member

  • Members
  • PipPip
  • 24 posts

Posted 20 February 2015 - 03:13 AM

Ran the car tonight. 1.6 seconds on a 35 foot track, ~288 mph scaled.

The best was when I ran it up the track and it took flight. Pure chaos in the room.

This was done with only 7.4V potential to the motor.

Tomorrow I going to make final speed runs with 14.8V potential.

Then see how far it can fly...

 

@David, I'm sure it could, but it would be badly shaken or all spilt from the journey



#5 EddieGarmon

EddieGarmon

    Member

  • Members
  • PipPip
  • 24 posts

Posted 20 February 2015 - 03:17 AM

And here is the code that went live... First production use of NETMF Tasks. 

using System;
using System.Threading;
using Microsoft.SPOT;
using uScoober.Extensions;
using uScoober.Hardware;
using uScoober.Hardware.Boards;
using uScoober.Hardware.Light;
using uScoober.Hardware.Motors;
using uScoober.IO;
using uScoober.IO.Native;
using uScoober.Threading;
using SL = SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace Outlaw.Derby
{
    public class Program
    {
        public static void Main() {
            //TaskScheduler.UnobservedExceptionHandler += exception => Debug.Print(exception.ToString());

            // warmup task engine
            Task.Run(() => { })
                .Wait();

            //wow, an IoT Pinewood Derby car? add some sensors...
            var car = new Car();
            car.Start();
        }
    }

    public class Car
    {
        private readonly Task _lightsManager;
        private readonly DigitalInput _modeSwitch;
        private readonly NetduinoPlus2 _netduino;
        private readonly BrushlessElectronicSpeedController _speedController;
        private readonly DigitalInput _triggerLock;
        private CancellationSource _cancelRace;
        private Modes _mode;
        private int _wantedPower;

        public Car() {
            _netduino = new NetduinoPlus2();
            _speedController = new BrushlessElectronicSpeedController(_netduino.PwmOut.D5);

            //initialize input listeners
            _modeSwitch = new DigitalInput(SL.Pins.GPIO_PIN_D1, "mode switch", ResistorMode.PullUp, InterruptMode.InterruptEdgeBoth, 50);
            _modeSwitch.InvertReading = true;
            _modeSwitch.OnInterupt += (source, state, time) => {
                                          _mode = _modeSwitch.Read() ? Modes.Staging : Modes.LightShow;
                                          _speedController.Stop();
                                      };

            _triggerLock = new DigitalInput(SL.Pins.GPIO_PIN_D2, "trigger-lock/e-stop", ResistorMode.PullUp, InterruptMode.InterruptEdgeBoth, 100);
            _triggerLock.InvertReading = true;
            _triggerLock.OnInterupt += (source, state, time) => {
                                           //fire on button down, coud use InterruptMode.InterruptEdgeLow
                                           if (!_triggerLock.Read()) {
                                               return;
                                           }

                                           switch (_mode) {
                                               case Modes.LightShow:
                                               case Modes.Celebrate:
                                               case Modes.Arming:
                                                   return;

                                               case Modes.Staging:
                                                   if (!StartingPinFound()) {
                                                       return;
                                                   }
                                                   _mode = Modes.Arming;
                                                   Thread.Sleep(1500);
                                                   if (!StartingPinFound()) {
                                                       _mode = Modes.Staging;
                                                       return;
                                                   }
                                                   SnapshotWantedPower();
                                                   _cancelRace = new CancellationSource();
                                                   Task.Run(token => {
                                                                while (StartingPinFound()) {
                                                                    _mode = Modes.Armed;
                                                                    //wait for the pin to drop, or cancellation
                                                                    token.ThrowIfCancellationRequested();
                                                                }
                                                                //Go Baby Go: fire all engines!
                                                                _mode = Modes.Race;
                                                                _speedController.SetPower(_wantedPower);
                                                                // todo: how long should we run?
                                                                int counter = 0;
                                                                while (counter < 2500) {
                                                                    if (token.IsCancellationRequested) {
                                                                        _speedController.Stop();
                                                                        token.ThrowIfCancellationRequested();
                                                                    }
                                                                    counter++;
                                                                    Thread.Sleep(1);
                                                                }
                                                            },
                                                            _cancelRace)
                                                       .ContinueWith(previous => {
                                                                         _speedController.Stop();
                                                                         _mode = (previous.IsCanceled) ? Modes.LightShow : Modes.Celebrate;
                                                                         _cancelRace = null;
                                                                     });
                                                   return;

                                               case Modes.Armed:
                                               case Modes.Race:
                                                   _speedController.Stop();
                                                   _cancelRace.Cancel();
                                                   return;

                                               default:
                                                   throw new ArgumentOutOfRangeException();
                                           }
                                       };

            _lightsManager = Task.New(() => {
                                          var leftFrontLed = new DigitalLed(new DigitalOutput(SL.Pins.GPIO_PIN_D13, false, "Left Front"));
                                          var rightFrontLed = new DigitalLed(new DigitalOutput(SL.Pins.GPIO_PIN_D12, false, "Right Front"));
                                          var leftRearLed = new DigitalLed(new DigitalOutput(SL.Pins.GPIO_PIN_D11, false, "Left Rear"));
                                          var rightRearLed = new DigitalLed(new DigitalOutput(SL.Pins.GPIO_PIN_D10, false, "Right Rear"));
                                          var random = new Random();
                                          int counter1 = 0;

                                          while (true) {
                                              bool flag;
                                              switch (_mode) {
                                                  case Modes.LightShow:
                                                      counter1 = (counter1 + 1) % 50;
                                                      if (counter1 == 1 || counter1 == 26) {
                                                          leftFrontLed.IsOn = random.NextBool();
                                                          leftRearLed.IsOn = random.NextBool();
                                                          rightFrontLed.IsOn = random.NextBool();
                                                          rightRearLed.IsOn = random.NextBool();
                                                      }
                                                      _netduino.OnboardLed.TurnOn(counter1 / 50.0);
                                                      break;
                                                  case Modes.Staging:
                                                      // blink left and right, front and back together
                                                      counter1 = (counter1 + 1) % 50;
                                                      flag = counter1 < 25;
                                                      leftFrontLed.IsOn = flag;
                                                      leftRearLed.IsOn = flag;
                                                      rightFrontLed.IsOn = !flag;
                                                      rightRearLed.IsOn = !flag;
                                                      _netduino.OnboardLed.IsOn = counter1 < 5;
                                                      break;
                                                  case Modes.Arming:
                                                      counter1 = (counter1 + 1) % 10;
                                                      flag = counter1 < 5;
                                                      leftFrontLed.IsOn = flag;
                                                      leftRearLed.IsOn = flag;
                                                      rightFrontLed.IsOn = flag;
                                                      rightRearLed.IsOn = flag;
                                                      _netduino.OnboardLed.IsOn = flag;
                                                      break;
                                                  case Modes.Armed:
                                                      // blink left and right front, rears on
                                                      counter1 = (counter1 + 1) % 50;
                                                      flag = counter1 < 25;
                                                      leftFrontLed.IsOn = flag;
                                                      leftRearLed.IsOn = true;
                                                      rightFrontLed.IsOn = !flag;
                                                      rightRearLed.IsOn = true;
                                                      _netduino.OnboardLed.TurnOn();
                                                      break;
                                                  case Modes.Race:
                                                      // fronts on, rears off
                                                      leftFrontLed.IsOn = true;
                                                      leftRearLed.IsOn = false;
                                                      rightFrontLed.IsOn = true;
                                                      rightRearLed.IsOn = false;
                                                      _netduino.OnboardLed.TurnOff();
                                                      break;
                                                  case Modes.Celebrate:
                                                      // fronts fast random, rears blink together
                                                      counter1 = (counter1 + 1) % 50;
                                                      flag = counter1 < 25;
                                                      if (counter1 == 1 || counter1 == 26) {
                                                          leftFrontLed.IsOn = random.NextBool();
                                                          rightFrontLed.IsOn = random.NextBool();
                                                      }
                                                      leftRearLed.IsOn = flag;
                                                      rightRearLed.IsOn = flag;
                                                      _netduino.OnboardLed.TurnOn((50 - counter1) / 50.0);
                                                      break;
                                                  default:
                                                      throw new ArgumentOutOfRangeException();
                                              }
                                              Thread.Sleep(10);
                                          }
                                      });
        }

        public void Start() {
            _netduino.OnboardLed.TurnOn();
            _speedController.Arm();
            _mode = Modes.LightShow;
            _modeSwitch.InteruptEnabled = true;
            _triggerLock.InteruptEnabled = true;
            _lightsManager.Start();
        }

        private void SnapshotWantedPower() {
            // 2 part scale
            // 0v to 1.6v => 0% to 50%
            // 1.6v to 2.15v => 50% to 100%

            var reading = _netduino.AnalogIn[2].Read();
            if (reading < 1.6) {
                _wantedPower = (int)((reading * 50) / 1.6);
            }
            else {
                _wantedPower = 50 + (int)(((reading - 1.6) * 50) / 0.55);
            }

            Debug.Print("Wanted Power:" + _wantedPower);
        }

        private bool StartingPinFound() {
            double light = _netduino.AnalogIn.A0.Read();
            Debug.Print("Start Light:" + light);
            return light >= 1.6;
        }

        private enum Modes
        {
            LightShow,
            Staging,
            Arming,
            Armed,
            Race,
            Celebrate
        }
    }
}



#6 EddieGarmon

EddieGarmon

    Member

  • Members
  • PipPip
  • 24 posts

Posted 02 March 2015 - 01:15 PM

And here it is in action: http://1drv.ms/1BCwT9Z



#7 beastyboy

beastyboy

    Advanced Member

  • Members
  • PipPipPip
  • 194 posts
  • LocationNetherlands

Posted 03 March 2015 - 09:17 PM

Nice going Eddie, that last run looked like demolition derby ! 


Van SchOten Ict Diensten en Services
http://www.voids.nl


#8 EddieGarmon

EddieGarmon

    Member

  • Members
  • PipPip
  • 24 posts

Posted 06 March 2015 - 03:37 PM

The code is now up on GitHub:

 

https://github.com/EddieGarmon/uDerby

 

And the libraries are at

 

https://github.com/E...Garmon/uScoober



#9 dotnetworker

dotnetworker

    Member

  • Members
  • PipPip
  • 12 posts
  • LocationNorth East England

Posted 02 May 2015 - 07:18 AM

And here it is in action: http://1drv.ms/1BCwT9Z

 

Loved the holy mackerel comment right at the end of the vid - guess it was a younger audience! ;)

Amazingly successful project well done!






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.