KP16 keypad returns wrong characters

Please tell me which signal is the card detected pin?

http://www.ghielectronics.com/downloads/schematic/SD_Card_Module_SCH.pdf

@ Gus - Yes, I know what this function does. And I like it a lot:

  1. I don’t need to read the manual to find out which pin is SD Detect. Especially if I am someone who is trying to dive into Gadgeteer world (or electronics as a subject). Why make it harder?
  2. It is easier to use this property when you are moving from one mainboard to another in a way that you don’t need to change pin each time you switch.

It seems to be quite strange decision. Why don’t you remove GHI.Pins namespace or SetDebugLED function? As you say, you can easily replicate those two. Overall, I don’t see what would be a reason to do it - do you want to save few bytes within your assembly?

@ iamin - I think these examples are very different.

@ Gus - Maybe they are. At the end of the day it is your decision, but I would love to see IsCardInserted within your assembly. In my understanding, it would be a step backwards in terms of user-friendliness if you decide to remove IsCardInserted.

Yes I want to use the Gadgeteer.Modules.GHIElectronics.sdCard, but it is non-functional. When I insert a SD card, nothing happens. The IsCardInserted property is always false, the IsCardMounted property is always false, the MountedEventHandler and UnmountedEventHandler never get called. Is this problem going to be fixed?

@ iamin - we hope and plan on making the libraries lean clean and simple, yet very useful and powerful. We want concentrate on the important things. I understand what you are saying though.

@ dspacek - Have you tried other SD cards?

No, I have an SD card that I know works with the SD card reader, I was using it ok with MF 4.2. Now I am using MF 4.3 latest release. I am using the Media Detection method shown here:
https://www.ghielectronics.com/docs/51/accessing-folders-and-files#476
The problem is that the property SDCard.IsCardPresent is always false.
So I created an InputPort object to read the card detected pin and that function works ok, so I am able to use the SD card because the GHI.IO.Storage.SDCard class, the RemovableMedia.Insert and RemovableMedia.Eject event properties do function ok.

The Gadgeteer.Modules.GHIElectronics.sdCard class is completely non-functional.

@ dspacek - the SDCard.IsCardPresent property does not function on the Raptor and is going to be removed entirely in the next SDK. As you said, you’ll want to create an interrupt/input port on the SD detect pin, pin 3 on the F socket (PD7 for the Raptor), and read it yourself.

The SDCard module functions fine for me on the Raptor using the latest SDK. Can you show me a minimal program that fails for you? Even though the SD card worked in 4.2, can you a try a different one anyway?

You are partially correct, but when a program starts up with the SD card already inserted, I do not get the mount event. If I remove the T43 display and the KP16 keypad, then I do get the mount event when the program starts.


//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.18444
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace SDCardTest {
    using Gadgeteer;
    using GTM = Gadgeteer.Modules;
    
    
    public partial class Program : Gadgeteer.Program {
        
        /// <summary>The SD Card module using socket 9 of the mainboard.</summary>
        private Gadgeteer.Modules.GHIElectronics.SDCard sdCard;
        
        /// <summary>The Display T43 module using sockets 15, 16, 17 and 14 of the mainboard.</summary>
        private Gadgeteer.Modules.GHIElectronics.DisplayT43 displayT43;
        
        /// <summary>The Keypad KP16 module using socket 18 of the mainboard.</summary>
        private Gadgeteer.Modules.GHIElectronics.KeypadKP16 keypadKP16;
        
        /// <summary>This property provides access to the Mainboard API. This is normally not necessary for an end user program.</summary>
        protected new static GHIElectronics.Gadgeteer.FEZRaptor Mainboard {
            get {
                return ((GHIElectronics.Gadgeteer.FEZRaptor)(Gadgeteer.Program.Mainboard));
            }
            set {
                Gadgeteer.Program.Mainboard = value;
            }
        }
        
        /// <summary>This method runs automatically when the device is powered, and calls ProgramStarted.</summary>
        public static void Main() {
            // Important to initialize the Mainboard first
            Program.Mainboard = new GHIElectronics.Gadgeteer.FEZRaptor();
            Program p = new Program();
            p.InitializeModules();
            p.ProgramStarted();
            // Starts Dispatcher
            p.Run();
        }
        
        private void InitializeModules() {
            this.sdCard = new GTM.GHIElectronics.SDCard(9);
            this.displayT43 = new GTM.GHIElectronics.DisplayT43(15, 16, 17, 14);
            this.keypadKP16 = new GTM.GHIElectronics.KeypadKP16(18);
        }
    }
}


using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.Hardware;
using System.Text;
using System.IO;
using Microsoft.SPOT.IO;
using GHI.IO.Storage;
using Gadgeteer.Modules.GHIElectronics;
using GHI.IO;
using GHI.Pins;
using GHI.Processor;
using GHI.Utilities;
using GHIElectronics.Gadgeteer;

namespace SDCardTest
{
    
    public partial class Program
    {
        private AutoResetEvent MountEvent;

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/
            
            MountEvent = new AutoResetEvent(false);
            sdCard.Mounted += sdCard_Mounted;
            sdCard.Unmounted += sdCard_Unmounted;
            new Thread(sdCardTest).Start();

            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
        }

        void sdCard_Unmounted(Gadgeteer.Modules.GHIElectronics.SDCard sender, EventArgs e)
        {
            Debug.Print("SDCard un-mounted event");
        }

        void sdCard_Mounted(Gadgeteer.Modules.GHIElectronics.SDCard sender, Gadgeteer.StorageDevice device)
        {
            Debug.Print("SDCard mounted event");
            MountEvent.Set();
        }


        void sdCardTest()
        {
            if (MountEvent.WaitOne(10000, false))
            {

                if (sdCard.IsCardInserted)
                {
                    Debug.Print("SDCard is inserted");
                    if (sdCard.IsCardMounted)
                    {
                        Debug.Print("SDCard is mounted");
                        // Assume only one storage device is available
                        // and that the media is formatted
                        string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
                        FileStream FileHandle = new FileStream(rootDirectory +
                                                      @ "\hello.txt", FileMode.Create);
                        byte[] data =
                           Encoding.UTF8.GetBytes("This string will go in the file!");
                        FileHandle.Write(data, 0, data.Length);
                        FileHandle.Close();
                    }
                }
            }
            else
            {
                Debug.Print("Time-out waiting for SDCard mounted event");
            }
        }

    }
}


@ dspacek - I ran your exact code on the recently released 2014 R3 and it behaved as expected. In order to get the file to write in time, I added a call to flush and unmount. You may want to change the if (MountEvent.WaitOne… to a while because it may take more than ten seconds to detect the card. I would also try a few different SD cards just to rule them out. Then try with just the keypad and then just the display and see what happens.

You are saying that if you insert an SD card, then reboot the Raptor, the program starts up with the SD card already inserted, and the mount event handler function sdCard_Mounted gets called?

@ dspacek - It appears there is a race condition. Sometimes you will get the mount event, other times you won’t. In the SDCard module constructor, it calls Mount() if it detects that the card is inserted. That raises the Mounted event sometime later. When you have the T43 and keypad in your program, the event is raised before you can subscribe to it in ProgramStarted because their initialization takes a non-trivial amount of time.

The solution for now is to not rely solely on the Mounted event but also check the IsCardInserted and IsCardMounted properties yourself at the start of the program.