In a previous pair of posts (part1 & part2) in February 2014 I built a 4WD Robot and remote control using a pair of Netduinos, an elecfreaks Smart Car Chassis 4WD, an elecfreaks joystick 2.4, an Embedded coolness nRF24Lo1 shield and a Pololu MC33926 motor shield.
My Quail device looked like a good platform for building a handheld control with a different form factor.
Bill of materials (prices in USD as at Jan 2016)
- MikroBUS.Net Quail Board USD49.00
- Mikroe Thumbstick click USD20.00
- Mikroe nRF-C click USD19.00
The Quail device and battery pack aren’t quite small enough to work with one hand. A Mikrobus.Net Dalmatian or Tuatara based remote might be easier to use.
I tried using the thumbstick button pushed message for the horn functionality but it made the throttle and heading jump.
The first version of the code is just to test the wireless link, the motor speed code needs a little work.(Currently the device won’t rotate with motors going in opposite directions)
public class Program { private const double Deadband = 0.1; private static double Scale = 100.0; private static byte RobotControlChannel = 10; private static byte[] ControllerAddress = Encoding.UTF8.GetBytes(&quot;RC1&quot;); private static byte[] RobotAddress = Encoding.UTF8.GetBytes(&quot;RB1&quot;); public static void Main() { ThumbstickClick thumbStick = new ThumbstickClick(Hardware.SocketThree); thumbStick.ThumbstickOrientation = ThumbstickClick.Orientation.RotateZeroDegrees; thumbStick.Calibrate(); NRFC nrf = new NRFC(Hardware.SocketFour); nrf.Configure(ControllerAddress, RobotControlChannel ); nrf.OnTransmitFailed += nrf_OnTransmitFailed; nrf.OnTransmitSuccess += nrf_OnTransmitSuccess; nrf.Enable(); while (true) { byte motor1Direction, motor2Direction; byte motor1Speed, motor2Speed; double x = thumbStick.GetPosition().X; double y = thumbStick.GetPosition().Y; Debug.Print("X=: + x.ToString("F1") + " Y=" + y.ToString("F1") + " IsPressed=" + thumbStick.IsPressed); // See if joystick x or y is in centre deadband if (System.Math.Abs(x) < Deadband) { x = 0.0; } // See if joystick y is in centre deadband if (System.Math.Abs(y) < Deadband) { y = 0.0; } // Set direction of both motors, no swivel on spot yet if (y >= 0.0) { motor1Direction = (byte)1; motor2Direction = (byte)1; } else { motor1Direction = (byte)0; motor2Direction = (byte)0; } // Straight ahead/backward if (x == 0.0) { motor1Speed = (byte)(System.Math.Abs(y) * Scale); motor2Speed = (byte)(System.Math.Abs(y) * Scale); } // Turning right else if (x > 0.0) { motor1Speed = (byte)(System.Math.Abs(y) * Scale); motor2Speed = (byte)(System.Math.Abs(y) * (1.0 - System.Math.Abs(x)) * Scale); } // Turning left else { motor1Speed = (byte)(System.Math.Abs(y) * (1.0 - System.Math.Abs(x)) * Scale); motor2Speed = (byte)(System.Math.Abs(y) * Scale); } Debug.Print("X=" + x.ToString("F1") + " Y=" + y.ToString("F1") + " IsPressed=" + thumbStick.IsPressed + " M1D=" + motor1Direction.ToString() + " M2D=" + motor2Direction.ToString() + " M1S=" + motor1Speed.ToString() + " M2S=" + motor2Speed.ToString()); byte[] command = { motor1Direction, motor2Direction, motor1Speed, motor2Speed, (byte)0) }; nrf.SendTo(RobotAddress, command ); MBN.Hardware.Led1.Write(true); Thread.Sleep(250); } } static void nrf_OnTransmitSuccess() { MBN.Hardware.Led1.Write(false); Debug.Print("nrf_OnTransmitSuccess"); } static void nrf_OnTransmitFailed() { Debug.Print("nrf_OnTransmitFailed"); } }
The Mikrobus.Net team have done a great job with the number and quality of the drivers for the Mikroe click boards. The Mikroe click boards are individually packaged with professionally written click specific and handling instructions.