.Net Gadgeteer: Robot

I’ll update this later today. But here is robot running a simple avoidance routine on .Net Gadgeteer.

Note: In the video, I meant to say “relatively high current” motor controller. Its certainly not high power. But it is overkill. ūüôā

Update: Source is now available: http://gotoloop.codeplex.com/

Advertisements

.Net Gadgeteer: IR Radar

In this demo I am going to show how to integrate with multiple external (non-Gadgeteer) hardware devices. 

In previous posts I have covered the basics of using a single extender module to connect to devices like a Bluetooth module. Here we show that it is possible to use several extenders. This is what I meant when I said .Net Gadgeteer is “hardware glue” in a previous post.

 

Suppose you wanted to connect a servo and an IR range finder (such as a Sharp GP2Y0A21F9Y)  to make a IR radar gadget. I want the servo to sweep the IR range finder across an arc and measure distance. Then I want the results to be displayed like a radar screen.

The issue you will run into is that there are no sockets that cover both PWM (needed by the servo) and analog input (needed by the IR range finder). This is a case where you must use multiple Extender Modules.

You could create your own extender module too. Just use the Extender Module that comes with the GHI kit have to map the pins with a voltmeter.

In this example, I opted to get another Extender Module. Here is what it looks like. Notice that the new one is using a straight header I soldered on. The other one uses a 90 degree header. This gives me more options later when prototyping. 

The code is very simple (works but could be improved):

   public partial class Program
    {
         void ProgramStarted()
        {
            // Do one-time tasks here
            Debug.Print("Program Started");
            GT.Interfaces.PWMOutput servo = this.extender.SetupPWMOutput(GT.Socket.Pin.Seven);//must be 7,8,9
            GT.Interfaces.AnalogInput IRRange = this.extender1.SetupAnalogInput(GT.Socket.Pin.Four);
            IRRange.Active = true;
            servo.Active = true;
            ushort minDistance = 0;
            ushort minDistanceTemp = 0;
            uint period = 20 * 1000 * 1000;
            uint hightime = 2000; //hightime range 700-2000 *1000
            uint minHightime = 0;
            int t = 0;
            int x0 = (int)(display.Width / 2);
            int y0 = (int)display.Height - 50;
            int x1 = 0;
            int y1 = 0;
            int factor;
            const int ANGLE_STEP_SIZE = 10;
            int diameter = 1500;
            int angle = 270;
            display.SimpleGraphics.SetPixel(GT.Color.White, 1, 1);
            servo.SetPulse(period, hightime * 1000);
            while (1 == 1)
            {
                for (hightime = 700; hightime                 
                {
                    diameter = 1500;
                    servo.SetPulse(period, hightime * 1000);;
                    factor =( diameter - minDistanceTemp) * ANGLE_STEP_SIZE * (int)System.Math.PI / 180 / 2;

                    x1 = ( factor *
                              (int)Microsoft.SPOT.Math.Sin(angle) / 1000) + (int)(display.Width / 2);
                    y1= (factor *
                              (int)Microsoft.SPOT.Math.Cos(angle) / 1000) +190;

                    //  line(x0, y0, x1, y1); //line takes too long to draw.
                    //using circles instead to show range.
                    display.SimpleGraphics.DisplayEllipse(GT.Color.Green, (uint)x1, (uint)y1, (uint)3, (uint)3);
                    angle -= ANGLE_STEP_SIZE;
                    if (angle < 90)
                    {
                        display.SimpleGraphics.Clear();
                        angle = 270;
                    }
                    System.Threading.Thread.Sleep(30);
                    minDistanceTemp = GP2D12ToCentimeters(IRRange.ReadProportion()*1000);
                    if (minDistanceTemp < minDistance || minDistance==0)
                    {                         
                        minDistance = minDistanceTemp;                        
                        minHightime = hightime;                     
                    }                 
                }             
            }         
        }         
        private UInt16 GP2D12ToCentimeters(double input)         
        {            
            UInt16 current=0;             
            if (input > 0)
            {
                //You can use Excel to calculate this function. 
                current = (UInt16)System.Math.Floor(System.Math.Pow((4187.9 / input), 1.1060));
                return current;
            }
            return current;
        }
    }

Note: if you have trouble with the Sharp IR sensor sometimes it helps to put a 30uf cap across vcc and gnd.

.Net Gadgeteer: Other Blogs/Resources

There is a growing number of online resources available for .Net Gadgeteer. I assume that everyone familiar with .Net Gadgeteer know about the following:

Here is a list of non-commercial sites:

Please feel free to forward other Gadgeteer resources.

.Net Gadgeteer: GPS Module

Seeed Studio has released a GPS module for .Net Gadgeteer. In this simple demonstration I am using Seeed Studio’s modules with the GHI’s mainboard with no issues to report. This is one of the really cool things about .Net Gadgeteer; it plays well with others. Gadgeteer is like cross vendor hardware glue that forms an eco-system. I will be talking more about that in later posts.

I am using Seeed Studio’s OLED display and showing off its vibrant colors.
Also note, I was too lazy to formet the latitude and longitude but in debug I verified it was accurate. According to the modules spec it is accurate to 2.5m. The Seeed Studio GPS module is based on the U-Blox Neo-6M GPS module.

The code is very simple:

public partial class Program
{
GTM.Seeed.GPS gps = new GTM.Seeed.GPS(8);
GTM.Seeed.OledDisplay oled = new GTM.Seeed.OledDisplay(6);

void ProgramStarted()
{
gps.InvalidPositionReceived += new GTM.Seeed.GPS.InvalidPositionReceivedHandler(gps_InvalidPositionReceived);
gps.PositionReceived += new GTM.Seeed.GPS.PositionReceivedHandler(gps_PositionReceived);
GT.Timer timer = new GT.Timer(5000);
timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
timer.Start();
}

void timer_Tick(GT.Timer timer)
{
Debug.Print("GPS last position " + gps.LastPosition + " age " + gps.LastValidPositionAge);
oled.SimpleGraphics.DisplayRectangle(GT.Color.Black, 0, GT.Color.Black, 10, 10, 120, 50);
oled.SimpleGraphics.DisplayText("GPS last position: " , Resources.GetFont(Resources.FontResources.small), GT.Color.Magenta, 10, 10);
oled.SimpleGraphics.DisplayText(" " + gps.LastPosition , Resources.GetFont(Resources.FontResources.small), GT.Color.Orange, 10, 20);
oled.SimpleGraphics.DisplayText("GPS age (days): " , Resources.GetFont(Resources.FontResources.small), GT.Color.Cyan, 10, 30);
oled.SimpleGraphics.DisplayText(" " + gps.LastValidPositionAge.Days, Resources.GetFont(Resources.FontResources.small), GT.Color.Blue, 10, 40);
}

void gps_InvalidPositionReceived(GTM.Seeed.GPS sender)
{
Debug.Print("Invalid position");
oled.SimpleGraphics.ClearNoRedraw();
oled.SimpleGraphics.DisplayText("GPS Threw: Invalid Position", Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 10, 10);
}

void gps_PositionReceived(GTM.Seeed.GPS sender, GTM.Seeed.GPS.Position position)
{
oled.SimpleGraphics.DisplayRectangle(GT.Color.Black, 0, GT.Color.Black, 10, 50, 120, 20);
oled.SimpleGraphics.DisplayText("GPS position: " , Resources.GetFont(Resources.FontResources.small), GT.Color.White, 10, 50);
oled.SimpleGraphics.DisplayText(" "+ position, Resources.GetFont(Resources.FontResources.small), GT.Color.Yellow, 10, 60);
}
}

That is all there is to it.

.Net Gadgeteer: Seeed Studio 128×128 OLED Display

This is one of the modules I was hoping to see; a small bright display. While the large 3.5″ display with touch that comes with GHI’s starter kit is impressive, for smaller devices and small robots its too large. Enter the 128×128 OLED. This display is bright and the perfect size for small device prototypes.

This OLED will be going on a robot. I am going to review a few more modules that are leading up to building a robot with .Net Gadgeteer.

The code is very simple:

display.SimpleGraphics.DisplayEllipse(GT.Color.Blue, 65, 65, 60, 50);
display.SimpleGraphics.DisplayText(".Net Gadgeteer", Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 30, 30);
display.SimpleGraphics.DisplayText(".Net Gadgeteer", Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 30, 40);
display.SimpleGraphics.DisplayText(".Net Gadgeteer", Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 30, 50);
display.SimpleGraphics.DisplayText("Rocks!!", Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 30, 60);

That is all there is to it.

.Net Gadgeteer; Servo Connection

A few days ago I¬†showed how to¬†hook¬†up¬†Sparkfun’s¬†Bluesmirf¬†modules. Today, I will show how to connect a servo to .Net Gadgeteer.

To determine which sockets are capable of PWM you can consult the GHI Gadgeteer site. There is a useful diagram there of the socket mapping:
As you can see the sockets with a “P” have PWM (this would be sockets 8,11). And on these socket’s pins 7,8,9 are the PWM pins. Code below better illustrates this.

The servo I am using an older micro servo, Cirrus cs-21bb, but this should work with most servos.

The pin connections to the server are very simple:

  • The servos ground wire (black ) is connected to the ground of your 5v external power source. And be sure to also connect ground to the Gedgeteer’s ground pin on the Extender Module.
  • The servos power wire (red ) is connected to your external power source’s positive(+).
  • The servos control wire (white) is connected to the Gadgeteer’s PWM output pin which is pin 7,8, or 9.

Here is a close up of the Extender Module wired to the servo:

As you can see the breadboards power rail is powered seperately from the Gadgeteer but the grounds are common. It is important that the grounds be common.

And here is a broader view of the set up:

Here is a code snippet:

      GT.Interfaces.PWMOutput servo = this.extender.SetupPWMOutput(GT.Socket.Pin.Seven);//must be pin 7,8,9
      servo.Active = true;
      while (1 == 1)
      {
         //full range of Cirrus cs-21bb servo, hightime range 700-2000
          for (UInt32 hightime = 700; hightime <= 2000; hightime += 72)          
           {
              servo.SetPulse(20 * 1000 * 1000, hightime * 1000);
              Debug.Print("High Time= " + hightime.ToString());
              System.Threading.Thread.Sleep(100);
          }
      }

And that is all there is to it. The class above will move the servo through a range and repeat. Enjoy.

.Net Gadgeteer Extender Module Header

In the previous post, I discussed how to connect Gadgeteer to a Bluetooth module. What I didn’t explain was the header on the Extender Module. It may seem obvious to some but the reason the module in my picture has a header is because I soldered one on…even better I had a friend who is better at soldering do it for me.

Here is the Extender Module sans header:

You can buy headers from various electronics supply stores. Digikey, Mouser, or allelectronics which I include a link for simply because they have a picture available.
Here is what a header looks like:

I used a 90 degree header but straight would be fine too. Just depends on how you want the module to be oriented when in a breadboard.
Again here is what it looks like when finished: