Example #1
0
        /// <summary>
        /// Searches the given list of com ports for a firmata device.
        /// </summary>
        /// <remarks>
        /// Scanning ports and testing for devices may affect unrelated devices. It is advisable to exclude ports known to contain other hardware from this scan.
        /// A board won't be found if its port is already open (by the same or a different process).
        /// </remarks>
        /// <param name="comPorts">List of com ports. Can be used with <see cref="SerialPort.GetPortNames"/>.</param>
        /// <param name="baudRates">List of baud rates to test. <see cref="CommonBaudRates"/>.</param>
        /// <param name="board">[Out] Returns the board reference. It is already initialized.</param>
        /// <returns>True on success, false if no board was found</returns>
        public static bool TryFindBoard(IEnumerable <string> comPorts, IEnumerable <int> baudRates,
#if !NETCOREAPP2_1
                                        [NotNullWhen(true)]
#endif
                                        out ArduinoBoard?board)
        {
            foreach (var port in comPorts)
            {
                foreach (var baud in baudRates)
                {
                    ArduinoBoard?b = null;
                    try
                    {
                        b = new ArduinoBoard(port, baud);
                        b.Initialize();
                        board = b;
                        return(true);
                    }
                    catch (Exception x) when(x is NotSupportedException || x is TimeoutException || x is IOException || x is UnauthorizedAccessException)
                    {
                        b?.Dispose();
                    }
                }
            }

            board = null !;
            return(false);
        }
Example #2
0
 public ArduinoAnalogInputPin(ArduinoBoard board, AnalogController controller, SupportedPinConfiguration configuration,
                              int pinNumber, ElectricPotential voltageReference)
     : base(controller, pinNumber, voltageReference)
 {
     _board         = board;
     _configuration = configuration;
 }
Example #3
0
 public ArduinoSpiDevice(ArduinoBoard board, SpiConnectionSettings connectionSettings)
 {
     Board = board;
     ConnectionSettings = connectionSettings;
     board.EnableSpi();
     board.Firmata.ConfigureSpiDevice(connectionSettings);
 }
Example #4
0
        /// <summary>
        /// Tries to connect to an arduino over network.
        /// This requires an arduino with an ethernet shield or an ESP32 with enabled WIFI support.
        /// </summary>
        /// <param name="boardAddress">The IP address of the board</param>
        /// <param name="port">The network port to use</param>
        /// <param name="board">Returns the board if successful</param>
        /// <returns>True on success, false otherwise</returns>
        public static bool TryConnectToNetworkedBoard(IPAddress boardAddress, int port,
#if NET5_0_OR_GREATER
                                                      [NotNullWhen(true)]
#endif
                                                      out ArduinoBoard?board)
        {
            board = null;
            try
            {
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Connect(boardAddress, port);
                socket.NoDelay = true;
                var networkStream = new NetworkStream(socket, true);
                board = new ArduinoBoard(networkStream);
                if (!(board.FirmataVersion > new Version(1, 0)))
                {
                    // Actually not expecting to get here (but the above will throw a SocketException if the remote end is not there)
                    throw new NotSupportedException("Very old firmware found on board");
                }

                return(true);
            }
            catch (SocketException)
            {
                return(false);
            }
        }
Example #5
0
        /// <summary>
        /// Create a PWM Channel on the Arduino. Depending on the board, it has 4-8 pins that support PWM.
        /// This expects to take the normal pin number (i.e. D6, D9) as input
        /// </summary>
        /// <param name="board">Reference to Board</param>
        /// <param name="chip">Always needs to be 0</param>
        /// <param name="channel">See above. Valid values depend on the board.</param>
        /// <param name="frequency">This parameter is ignored and exists only for compatibility</param>
        /// <param name="dutyCyclePercentage">PWM duty cycle (0 - 1)</param>
        public ArduinoPwmChannel(ArduinoBoard board,
                                 int chip,
                                 int channel,
                                 int frequency = 400,
                                 double dutyCyclePercentage = 0.5)
        {
            Chip = chip;
            if (chip != 0)
            {
                throw new NotSupportedException("No such chip: {0}");
            }

            Channel = channel;
            _pin    = channel;
            var caps = board.SupportedPinConfigurations.FirstOrDefault(x => x.Pin == _pin);

            if (caps == null || !caps.PinModes.Contains(SupportedMode.Pwm))
            {
                throw new NotSupportedException($"Pin {_pin} does not support PWM");
            }

            _frequency = frequency;
            _dutyCycle = dutyCyclePercentage;
            _board     = board;
            _enabled   = false;
        }
Example #6
0
        public ArduinoAnalogController(ArduinoBoard board,
                                       IReadOnlyList <SupportedPinConfiguration> supportedPinConfigurations, PinNumberingScheme scheme)
            : base(scheme)
        {
            _board = board ?? throw new ArgumentNullException(nameof(board));
            _supportedPinConfigurations = supportedPinConfigurations ?? throw new ArgumentNullException(nameof(supportedPinConfigurations));
            PinCount = _supportedPinConfigurations.Count;

            // Note: While the Arduino does have an external analog input reference pin, Firmata doesn't allow configuring it.
            VoltageReference = ElectricPotential.FromVolts(5.0);
        }
        internal ArduinoGpioControllerDriver(ArduinoBoard arduinoBoard, IReadOnlyCollection <SupportedPinConfiguration> supportedPinConfigurations)
        {
            _arduinoBoard = arduinoBoard ?? throw new ArgumentNullException(nameof(arduinoBoard));
            _supportedPinConfigurations = supportedPinConfigurations ?? throw new ArgumentNullException(nameof(supportedPinConfigurations));
            _callbackContainers         = new Dictionary <int, CallbackContainer>();
            _waitForEventResetEvent     = new AutoResetEvent(false);
            _callbackContainersLock     = new object();
            _pinModes = new ConcurrentDictionary <int, PinMode>();

            PinCount = _supportedPinConfigurations.Count;
            _arduinoBoard.Firmata.DigitalPortValueUpdated += FirmataOnDigitalPortValueUpdated;
        }
Example #8
0
        public ArduinoI2cDevice(ArduinoBoard board, ArduinoI2cBus bus, I2cConnectionSettings connectionSettings)
        {
            _board = board ?? throw new ArgumentNullException(nameof(board));
            _bus   = bus ?? throw new ArgumentNullException(nameof(bus));

            if (connectionSettings == null)
            {
                throw new ArgumentNullException(nameof(connectionSettings));
            }

            if (connectionSettings.BusId != 0)
            {
                throw new NotSupportedException("Only I2C Bus 0 is supported");
            }

            if (connectionSettings.DeviceAddress > 127)
            {
                throw new NotSupportedException("The device address must be less than 128.");
            }

            ConnectionSettings = connectionSettings;

            // Ensure the corresponding pins are set to I2C (not strictly necessary, but consistent)
            foreach (SupportedPinConfiguration supportedPinConfiguration in _board.SupportedPinConfigurations.Where(x => x.PinModes.Contains(SupportedMode.I2c)))
            {
                _board.Firmata.SetPinMode(supportedPinConfiguration.Pin, SupportedMode.I2c);
            }

            _board.Firmata.SendI2cConfigCommand();

            // Sometimes, the very first I2C command fails (nothing happens), so try reading a byte
            int retries = 3;

            while (retries-- > 0)
            {
                try
                {
                    ReadByte();
                    break;
                }
                catch (Exception x) when(x is TimeoutException || x is IOException)
                {
                }
            }

            // If the above still failed, there's probably no device on the other end. But this shall not throw here but only if
            // the client calls ReadByte.
        }
Example #9
0
 /// <summary>
 /// This is internally called when the command handler is registered
 /// </summary>
 internal void Registered(FirmataDevice firmata, ArduinoBoard board)
 {
     _firmata = firmata;
     _board   = board;
     _firmata.OnSysexReply += OnSysexDataInternal;
 }
Example #10
0
 public ArduinoI2cBus(ArduinoBoard board, int busId)
 {
     _board         = board;
     _busId         = busId;
     _usedAddresses = new HashSet <int>();
 }