Cerbuino Analog Inputs Confusion

Hi,

I’ve been having some trouble with the pin enumeration on my Cerbuino for Analog inputs.

I have a joystick module connected to socket 2 and, from cross referencing the schematics of the module and the mainboard, I’m pretty sure that the two analog inputs for axis x and y are PA2 and PA3.

Using the following, PA2 works fine;

Joystick_x = new AnalogInput((Cpu.AnalogChannel)GHI.Hardware.FEZCerb.Pin.PA2);

But the following causes an exception;

Joystick_y = new AnalogInput((Cpu.AnalogChannel)GHI.Hardware.FEZCerb.Pin.PA3);

The exception breaks on a digital output (PC0) in a different socket, that I’m using for the character display;

LCD_E = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin3, false);

I tested it in a gadgeteer app and it all worked fine so I was sure that it was something that I was doing wrong. Anyway, I did some digging in the gadgeteer source code and found this in the socket 2 section;

socket.AnalogueInput5 = Cpu.AnalogChannel.ANALOG_2;

This surprised me because the Cerbuino schematic suggests that it should be ANALOG_3 (it’s labelled as ADC123_IN3). Regardless I’ve tried the following and it’s now working fine;

Joystick_x = new AnalogInput(Cpu.AnalogChannel.ANALOG_1);
Joystick_y = new AnalogInput(Cpu.AnalogChannel.ANALOG_2);

So my question is, is there an error somewhere in the pin allocation for PA3 (because PA2 enum works fine) or have I misunderstood how the analog channels are allocated and/or connected. I want to use other analog inputs so I’d like to fully understand how they work.

Thanks

Microsoft’s implementation of AnalogIn uses a particular pin enumeration and it is up to the manufacturer how to map those pins to that enumeration.

Here is a link that will be helpful to the pin map enumeration: https://www.ghielectronics.com/docs/46/cerb-family#403

@ Aron - Thanks for the link.

That seems to prove what I found, that PA3 is ANALOG_2. So any idea why GHI.Hardware.FEZCerb.Pin.PA3 doesn’t work and causes a conflict with PC0?

I’d rather be using the GHI.Hardware.FEZCerb.Pin enums because that matches the labelling on the schematic.

What kind of program are you trying to run, Gadgeteer or Console?

Console.

When I tested it with a gadgeteer app and the designer it worked fine, which is what led to finding out that it was ANALOG_2 from the source code. Like I said in the OP, the PA2 enum works fine but PA3 doesn’t.

Can you provide the sample program that gives the error? I would like to run the same application to verify the results. Also provide complete setup as to which modules and which sockets they are in and how you are powering the board.

Powered by USB. I haven’t tried with a PSU yet because it works fine in Gadgeteer and with ANALOG_2 enums. I can’t see it being that.

GHI character display is in socket 3, joystick in socket 2. I also have an arduino CANbus shield in the six pin SMT and the eight pin directly opposite.

If it’s a totally noob coding error on my part, please be kind! :slight_smile:


using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHI.Hardware.FEZCerb;
using HD44780_Driver;

namespace MFConsoleApplication1
{
    public class Program
    {
        // Set up analogue channels for the joystick
        static AnalogInput Joystick_x = new AnalogInput((Cpu.AnalogChannel)Pin.PA2);
        static double Joy_x = 0;
        static AnalogInput Joystick_y = new AnalogInput((Cpu.AnalogChannel)Pin.PA3);
        static double Joy_y = 0;

        static Display_HD44780 disp = new Display_HD44780(3);

        public static void Main()
        {
            disp.Clear();

            while (true)
            {
                Joy_x = Joystick_x.Read();
                disp.CursorHome();
                disp.PrintString("x = " + Joy_x.ToString("F2"));
                Joy_y = Joystick_y.Read();
                disp.SetCursor(1, 0);
                disp.PrintString("y = " + Joy_y.ToString("F2"));
                Thread.Sleep(500);
            }
        }

    }
}
using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;
using CerbBeePins_Config;

namespace HD44780_Driver
{
    /// <summary>
    /// A Display_HD44780 module for Microsoft .NET Gadgeteer
    /// </summary>
    public class Display_HD44780
    {
        private OutputPort LCD_RS;
        private OutputPort LCD_E;

        private OutputPort LCD_D4;
        private OutputPort LCD_D5;
        private OutputPort LCD_D6;
        private OutputPort LCD_D7;

        private OutputPort BackLight;

        const byte DISP_ON = 0xC;    //Turn visible LCD on
        const byte CLR_DISP = 1;      //Clear display
        const byte CUR_HOME = 2;      //Move cursor home and clear screen memory
        const byte SET_CURSOR = 0x80;   //SET_CURSOR + X : Sets cursor position to X

        // Note: A constructor summary is auto-generated by the doc builder.
        /// <summary></summary>
        /// <param name="socketNumber">The socket that this module is plugged in to.</param>
        public Display_HD44780(int socketNumber)
        {
            switch (socketNumber)
            {
                case 1:
                    LCD_RS = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin4, false);
                    LCD_E = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin3, false);
                    LCD_D4 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin5, false);
                    LCD_D5 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin7, false);
                    LCD_D6 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin9, false);
                    LCD_D7 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin6, false);
                    BackLight = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket1.Pin8, true);
                    break;
                case 2:
                    LCD_RS = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin4, false);
                    LCD_E = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin3, false);
                    LCD_D4 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin5, false);
                    LCD_D5 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin7, false);
                    LCD_D6 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin9, false);
                    LCD_D7 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin6, false);
                    BackLight = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket2.Pin8, true);
                    break;
                case 3:
                    LCD_RS = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin4, false);
                    LCD_E = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin3, false);
                    LCD_D4 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin5, false);
                    LCD_D5 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin7, false);
                    LCD_D6 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin9, false);
                    LCD_D7 = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin6, false);
                    BackLight = new OutputPort(FEZCerbuino.Pin.Gadgeteer.Socket3.Pin8, true);
                    break;
                default:
                    throw new Exception("No socketNumber value found");
            }
            
            Initialize();
        }

        /// <summary>
        /// This function will enable the display, clean it, and enter 4-bit mode.
        /// </summary>
        private void Initialize()
        {
            LCD_RS.Write(false);

            // 4 bit data communication
            Thread.Sleep(50);

            LCD_D7.Write(false);
            LCD_D6.Write(false);
            LCD_D5.Write(true);
            LCD_D4.Write(true);

            LCD_E.Write(true);
            LCD_E.Write(false);

            Thread.Sleep(50);

            LCD_D7.Write(false);
            LCD_D6.Write(false);
            LCD_D5.Write(true);
            LCD_D4.Write(true);

            LCD_E.Write(true);
            LCD_E.Write(false);

            Thread.Sleep(50);

            LCD_D7.Write(false);
            LCD_D6.Write(false);
            LCD_D5.Write(true);
            LCD_D4.Write(true);

            LCD_E.Write(true);
            LCD_E.Write(false);

            Thread.Sleep(50);

            LCD_D7.Write(false);
            LCD_D6.Write(false);
            LCD_D5.Write(true);
            LCD_D4.Write(false);

            LCD_E.Write(true);
            LCD_E.Write(false);

            SendCmd(DISP_ON);
            SendCmd(CLR_DISP);
        }

        ///<summary>
        /// Sends an LCD command.
        /// </summary>
        private void SendCmd(byte c)
        {
            LCD_RS.Write(false); //set LCD to data mode

            LCD_D7.Write((c & 0x80) != 0);
            LCD_D6.Write((c & 0x40) != 0);
            LCD_D5.Write((c & 0x20) != 0);
            LCD_D4.Write((c & 0x10) != 0);
            LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin

            LCD_D7.Write((c & 0x08) != 0);
            LCD_D6.Write((c & 0x04) != 0);
            LCD_D5.Write((c & 0x02) != 0);
            LCD_D4.Write((c & 0x01) != 0);
            LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin

            Thread.Sleep(1);

            LCD_RS.Write(true); //set LCD to data mode
        }

        /// <summary>
        /// Prints the passed in string to the screen at the current cursor position. Note: This function will move the cursor position after.
        /// </summary>
        /// <param name="str">The string to print.</param>
        public void PrintString(string str)
        {
            for (int i = 0; i < str.Length; i++)
                Putc((byte)str[i]);
        }

        /// <summary>
        /// Sends an ASCII character to the LCD at the current cursor position. Note: This function will move the cursor position after.
        /// </summary>
        /// <param name="c">The character to display.</param>
        public void Putc(byte c)
        {
            LCD_D7.Write((c & 0x80) != 0);
            LCD_D6.Write((c & 0x40) != 0);
            LCD_D5.Write((c & 0x20) != 0);
            LCD_D4.Write((c & 0x10) != 0);
            LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin

            LCD_D7.Write((c & 0x08) != 0);
            LCD_D6.Write((c & 0x04) != 0);
            LCD_D5.Write((c & 0x02) != 0);
            LCD_D4.Write((c & 0x01) != 0);
            LCD_E.Write(true); LCD_E.Write(false); //Toggle the Enable Pin
            //Thread.Sleep(1);
        }

        /// <summary>
        /// Clears the screen.
        /// </summary>
        public void Clear()
        {
            SendCmd(CLR_DISP);
        }

        /// <summary>
        /// Places the cursor at the top left of the screen.
        /// </summary>
        public void CursorHome()
        {
            SendCmd(CUR_HOME);
        }

        /// <summary>
        /// Set the cursor to the passed in position.
        /// </summary>
        /// <param name="row">Row of the desired cursor position.</param>
        /// <param name="col">Column of the desired cursor position.</param>
        public virtual void SetCursor(byte row, byte col)
        {
            byte[] row_offsets = new byte[4] { 0x00, 0x40, 0x14, 0x54 };
            SendCmd((byte)(SET_CURSOR | row_offsets[row] | col));
        }

        /// <summary>
        /// Turns the backlight on.
        /// </summary>
        public void TurnBacklightOn()
        {
            BackLight.Write(true);
        }

        /// <summary>
        /// Turns the backlight off.
        /// </summary>
        public void ShutBacklightOff()
        {
            BackLight.Write(false);
        }
    }
}

using GHI.Hardware.FEZCerb;
using Microsoft.SPOT.Hardware;

namespace CerbBeePins_Config
{

    /// <summary>
    /// Exposes FEZ Cerbuino specific functionality.
    /// </summary>
    public static class FEZCerbuino
    {
        /// <summary>
        /// Provides Pin definitions for FEZ Cerbuino.
        /// </summary>
        public class Pin
        {
            /// <summary>
            /// Provides Pin definitions for FEZ Cerbuino's Arduino-styled I/O headers.
            /// </summary>
            public class Digital
            {
                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin A0 = GHI.Hardware.FEZCerb.Pin.PB1;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin A1 = GHI.Hardware.FEZCerb.Pin.PA5;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin A2 = GHI.Hardware.FEZCerb.Pin.PB0;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin A3 = GHI.Hardware.FEZCerb.Pin.PC3;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin A4 = GHI.Hardware.FEZCerb.Pin.PC1;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin A5 = GHI.Hardware.FEZCerb.Pin.PA4;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D0 = GHI.Hardware.FEZCerb.Pin.PB11;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D1 = GHI.Hardware.FEZCerb.Pin.PB10;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D2 = GHI.Hardware.FEZCerb.Pin.PB12;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D3 = GHI.Hardware.FEZCerb.Pin.PC14;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D4 = GHI.Hardware.FEZCerb.Pin.PC15;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D5 = GHI.Hardware.FEZCerb.Pin.PA8;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D6 = GHI.Hardware.FEZCerb.Pin.PA10;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D7 = GHI.Hardware.FEZCerb.Pin.PC4;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D8 = GHI.Hardware.FEZCerb.Pin.PB13;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D9 = GHI.Hardware.FEZCerb.Pin.PA9;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D10 = GHI.Hardware.FEZCerb.Pin.PA15;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D11 = GHI.Hardware.FEZCerb.Pin.PB5;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D12 = GHI.Hardware.FEZCerb.Pin.PB4;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin D13 = GHI.Hardware.FEZCerb.Pin.PB3;

                /// <summary>Digital I/O.</summary>
                public const Cpu.Pin LED1 = GHI.Hardware.FEZCerb.Pin.PB2;

            }

            /// <summary>
            /// Provides Pin definitions for FEZ Cerbuino's Gadgeteer sockets.
            /// </summary>
            public class Gadgeteer
            {
                /// <summary>
                /// Provides Pin definitions for FEZ Cerbuino's Socket 1.
                /// </summary>
                public class Socket1
                {
                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin3 = GHI.Hardware.FEZCerb.Pin.PA14;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin4 = GHI.Hardware.FEZCerb.Pin.PB10;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin5 = GHI.Hardware.FEZCerb.Pin.PB11;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin6 = GHI.Hardware.FEZCerb.Pin.PA13;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin7 = GHI.Hardware.FEZCerb.Pin.PB5;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin8 = GHI.Hardware.FEZCerb.Pin.PB4;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin9 = GHI.Hardware.FEZCerb.Pin.PB3;

                }

                /// <summary>
                /// Provides Pin definitions for FEZ Cerbuino's Socket 2.
                /// </summary>
                public class Socket2
                {
                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin3 = GHI.Hardware.FEZCerb.Pin.PA6;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin4 = GHI.Hardware.FEZCerb.Pin.PA2;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin5 = GHI.Hardware.FEZCerb.Pin.PA3;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin6 = GHI.Hardware.FEZCerb.Pin.PA1;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin7 = GHI.Hardware.FEZCerb.Pin.PA0;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin8 = GHI.Hardware.FEZCerb.Pin.PB7;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin9 = GHI.Hardware.FEZCerb.Pin.PB6;

                }

                /// <summary>
                /// Provides Pin definitions for FEZ Cerbuino's Socket 3.
                /// </summary>
                public class Socket3
                {
                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin3 = GHI.Hardware.FEZCerb.Pin.PC0;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin4 = GHI.Hardware.FEZCerb.Pin.PC1;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin5 = GHI.Hardware.FEZCerb.Pin.PA4;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin6 = GHI.Hardware.FEZCerb.Pin.PC5;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin7 = GHI.Hardware.FEZCerb.Pin.PB8;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin8 = GHI.Hardware.FEZCerb.Pin.PA7;

                    /// <summary>Digital I/O.</summary>
                    public const Cpu.Pin Pin9 = GHI.Hardware.FEZCerb.Pin.PB9;

                }


            }

            /// <summary>
            /// Provides Channel definitions for FEZ Cerbuino's PWM capable pins.
            /// </summary>
            public class PWM
            {
                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D5 = (Cpu.PWMChannel)3;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel A2 = (Cpu.PWMChannel)4;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel A0 = (Cpu.PWMChannel)5;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D11 = (Cpu.PWMChannel)6;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D12 = (Cpu.PWMChannel)7;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D13 = (Cpu.PWMChannel)8;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D0 = (Cpu.PWMChannel)9;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D1 = (Cpu.PWMChannel)10;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D6 = (Cpu.PWMChannel)11;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D9 = (Cpu.PWMChannel)12;

                /// <summary>PWM Output</summary>
                public const Cpu.PWMChannel D10 = (Cpu.PWMChannel)13;

            }

            /// <summary>
            /// Provides Channel definitions for FEZ Cerbuino's AnalogIn capable pins.
            /// </summary>
            public class AnalogIn
            {
                /// <summary>Analog Input</summary>
                public const Cpu.AnalogChannel A0 = (Cpu.AnalogChannel)10;

                /// <summary>Analog Input</summary>
                public const Cpu.AnalogChannel A1 = (Cpu.AnalogChannel)8;

                /// <summary>Analog Input</summary>
                public const Cpu.AnalogChannel A2 = (Cpu.AnalogChannel)9;

                /// <summary>Analog Input</summary>
                public const Cpu.AnalogChannel A3 = (Cpu.AnalogChannel)7;

                /// <summary>Analog Input</summary>
                public const Cpu.AnalogChannel A4 = (Cpu.AnalogChannel)4;

                /// <summary>Analog Input</summary>
                public const Cpu.AnalogChannel A5 = (Cpu.AnalogChannel)5;

            }

        }
    }
}

Any joy with this?

@ wolfbuddy

Sorry, I have not had the opportunity to test this yet. I will test it as soon as I can.

@ Aron - OK thanks, no problem.