SolidSoils / Arduino

C# .NET - Arduino library supporting simultaneous serial ASCII, Firmata and I2C communication
https://solidsoils.github.io/Arduino/index.html
BSD 2-Clause "Simplified" License
200 stars 61 forks source link

Event OnDigitalStateReceived don't work in Winforms #39

Closed Armagedon13 closed 3 years ago

Armagedon13 commented 3 years ago

Hi im new in c#(Programming in general) but i have a small program to control a led in pin 13 by button in pin 8:

using Solid.Arduino;
using Solid.Arduino.Firmata;
using System;
using System.Windows.Forms;

namespace Arduino_Firmata_Connection
{
    public partial class Client : Form
    {
        public Solid.Arduino.ArduinoSession session = new Solid.Arduino.ArduinoSession(new EnhancedSerialConnection("COM4", SerialBaudRate.Bps_57600));
        public Client()
        {
            InitializeComponent();
            ArduinoConnection();
        }

        public void ArduinoConnection()
        {
            session.SetDigitalPinMode(8, PinMode.InputPullup);
            session.SetDigitalReportMode(8, true);
            session.SetDigitalPinMode(13, PinMode.DigitalOutput);
            session.DigitalStateReceived += Session_OnDigitalStateReceived;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            session.SetDigitalPin(13, true);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            session.SetDigitalPin(13, false);
        }
        private void Session_OnDigitalStateReceived(object sender, FirmataEventArgs<DigitalPortState> eventArgs)
        {
            session.SetDigitalPin(13, true);
        }
    }
}

The button in winforms works but the button connected to arduino doesn't.

SolidSoils commented 3 years ago

Hi, the DigitalStateReceived event is triggered when data is received from your Arduino board. The board must be instructed to send digital pin state messages. This is done by method IFirmataProtocol.SetDigitalReportMode(int portNumber, bool enable). I do not see this instruction in your code, so I expect event handler Session_OnDigitalStateReceived not to be invoked.

Which button is "connected" to your Arduino board?

Armagedon13 commented 3 years ago

Hi thanks for reply , i have a InputPullup in pin 8 and the button wired to ground , i have session.SetDigitalReportMode(8, true); in public void ArduinoConnection() is not the same?

SolidSoils commented 3 years ago

Ah, I see. Does your Arduino send a Firmata-message when you press the button wired to pin 8?

Armagedon13 commented 3 years ago

in arduino code i uploaded Standar Firmata version 2.5.8 when i push the button in pin 8 trigger this event no?

private void Session_OnDigitalStateReceived(object sender, FirmataEventArgs<DigitalPortState> eventArgs)
 {
           session.SetDigitalPin(13, true);
 }

when the event is triggered put the pin 13 HIGH session.SetDigitalPin(13, true); i don't know why this doesn't work

Armagedon13 commented 3 years ago

i'm reading the documentation and looking for examples but they looks like mine see #24 for example.

IFirmataProtocol.CreateDigitalStateMonitor Method (Int32) but i don't know how it works.

SolidSoils commented 3 years ago

The Monitor methods return IObservable objects. These are used in WPF and Unified Windows components.

The issue you have with your code is the following: with session.SetDigitalReportMode(8, true) you attempt to set the report mode on port 8. Of course, this port does not exist. Pins are grouped by ports. E.g. your pin 8 could be bit 0 of port 1. (I am not sure, so please check and double-check!)

In the event handler pin-changes to your port can be retrieved from the event args (FirmataEventArgs<DigitalPortState>). You can test if the desired pin is set like this: if (eventArgs.Value.IsSet(0)) { }

Armagedon13 commented 3 years ago

yes, it worked session.SetDigitalReportMode (1, true), I thought I had to put the pin used, not the port used. Now and if I want to put more pins, the first pin set is the first port? and if I want the events to be separated by the activated pins or with the same event, read the state of the pins? thanks for all i'm see all this.

zoltantajti commented 10 months ago

Hello guys. I have same, this problem.

session.SetDigitalPinMode(8, PinMode.InputPullup);
session.SetDigitalReportMode(8, true);
session.SetDigitalPinMode(13, PinMode.DigitalOutput);
session.DigitalStateReceived += (sender, eventArgs) =>
{
    Trace.WriteLine(eventArgs.ToString());
    Trace.WriteLine("OK");
};

And when I press the Pin8 button, doesn't happening. The Trace Writeline doesn't show the "OK"

SolidSoils commented 10 months ago

@zoltantajti The first parameter of method SetDigitalReportMode(int portNumber, bool enable) identifies a port, not a pin. This is because the Firmata protocol does not report pin states individually, but grouped in ports.

Pins 8 and 13 are probably on port 1 and in that case line 2 should be:

session.SetDigitalReportMode(1, true);

Best practice is to set the report mode as a very last step. It will trigger the Arduino board to send an initial digital state message for pins 8 and 13 which by then have been properly set up and that message can then be processed by the DigitalStateReceived handler.